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 2015/01/08 14:17:29 UTC
[09/13] syncope git commit: [SYNCOPE-620] server logic in,
tests missing
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/PolicyController.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/PolicyController.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/PolicyController.java
new file mode 100644
index 0000000..fbfb127
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/PolicyController.java
@@ -0,0 +1,197 @@
+/*
+ * 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.server.logic;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.syncope.common.lib.to.AbstractPolicyTO;
+import org.apache.syncope.common.lib.to.AccountPolicyTO;
+import org.apache.syncope.common.lib.to.PasswordPolicyTO;
+import org.apache.syncope.common.lib.to.SyncPolicyTO;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.syncope.persistence.api.dao.NotFoundException;
+import org.apache.syncope.persistence.api.dao.PolicyDAO;
+import org.apache.syncope.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.persistence.api.entity.PasswordPolicy;
+import org.apache.syncope.persistence.api.entity.Policy;
+import org.apache.syncope.persistence.api.entity.SyncPolicy;
+import org.apache.syncope.server.logic.data.PolicyDataBinder;
+import org.apache.syncope.server.logic.init.ImplementationClassNamesLoader;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class PolicyController extends AbstractTransactionalLogic<AbstractPolicyTO> {
+
+ @Autowired
+ private ImplementationClassNamesLoader classNamesLoader;
+
+ @Autowired
+ private PolicyDAO policyDAO;
+
+ @Autowired
+ private PolicyDataBinder binder;
+
+ @PreAuthorize("hasRole('POLICY_CREATE')")
+ public <T extends AbstractPolicyTO> T create(final T policyTO) {
+ return binder.getPolicyTO(policyDAO.save(binder.getPolicy(null, policyTO)));
+ }
+
+ private <T extends AbstractPolicyTO, K extends Policy> T update(final T policyTO, final K policy) {
+ binder.getPolicy(policy, policyTO);
+ K savedPolicy = policyDAO.save(policy);
+ return binder.getPolicyTO(savedPolicy);
+ }
+
+ @PreAuthorize("hasRole('POLICY_UPDATE')")
+ public PasswordPolicyTO update(final PasswordPolicyTO policyTO) {
+ Policy policy = policyDAO.find(policyTO.getId());
+ if (!(policy instanceof PasswordPolicy)) {
+ throw new NotFoundException("PasswordPolicy with id " + policyTO.getId());
+ }
+
+ return update(policyTO, policy);
+ }
+
+ @PreAuthorize("hasRole('POLICY_UPDATE')")
+ public AccountPolicyTO update(final AccountPolicyTO policyTO) {
+ Policy policy = policyDAO.find(policyTO.getId());
+ if (!(policy instanceof AccountPolicy)) {
+ throw new NotFoundException("AccountPolicy with id " + policyTO.getId());
+ }
+
+ return update(policyTO, policy);
+ }
+
+ @PreAuthorize("hasRole('POLICY_UPDATE')")
+ public SyncPolicyTO update(final SyncPolicyTO policyTO) {
+ Policy policy = policyDAO.find(policyTO.getId());
+ if (!(policy instanceof SyncPolicy)) {
+ throw new NotFoundException("SyncPolicy with id " + policyTO.getId());
+ }
+
+ return update(policyTO, policy);
+ }
+
+ @PreAuthorize("hasRole('POLICY_LIST')")
+ @SuppressWarnings("unchecked")
+ public <T extends AbstractPolicyTO> List<T> list(final PolicyType type) {
+
+ List<? extends Policy> policies = policyDAO.find(type);
+
+ final List<T> policyTOs = new ArrayList<T>();
+ for (Policy policy : policies) {
+ policyTOs.add((T) binder.getPolicyTO(policy));
+ }
+
+ return policyTOs;
+ }
+
+ @PreAuthorize("hasRole('POLICY_READ')")
+ public PasswordPolicyTO getGlobalPasswordPolicy() {
+ PasswordPolicy policy = policyDAO.getGlobalPasswordPolicy();
+ if (policy == null) {
+ throw new NotFoundException("No password policy found");
+ }
+
+ return (PasswordPolicyTO) binder.getPolicyTO(policy);
+ }
+
+ @PreAuthorize("hasRole('POLICY_READ')")
+ public AccountPolicyTO getGlobalAccountPolicy() {
+ AccountPolicy policy = policyDAO.getGlobalAccountPolicy();
+ if (policy == null) {
+ throw new NotFoundException("No account policy found");
+ }
+
+ return (AccountPolicyTO) binder.getPolicyTO(policy);
+ }
+
+ @PreAuthorize("hasRole('POLICY_READ')")
+ public SyncPolicyTO getGlobalSyncPolicy() {
+ SyncPolicy policy = policyDAO.getGlobalSyncPolicy();
+ if (policy == null) {
+ throw new NotFoundException("No sync policy found");
+ }
+
+ return (SyncPolicyTO) binder.getPolicyTO(policy);
+ }
+
+ @PreAuthorize("hasRole('POLICY_READ')")
+ public <T extends AbstractPolicyTO> T read(final Long id) {
+ Policy policy = policyDAO.find(id);
+ if (policy == null) {
+ throw new NotFoundException("Policy " + id + " not found");
+ }
+
+ return binder.getPolicyTO(policy);
+ }
+
+ @PreAuthorize("hasRole('POLICY_DELETE')")
+ public <T extends AbstractPolicyTO> T delete(final Long id) {
+ Policy policy = policyDAO.find(id);
+ if (policy == null) {
+ throw new NotFoundException("Policy " + id + " not found");
+ }
+
+ T policyToDelete = binder.getPolicyTO(policy);
+ policyDAO.delete(policy);
+
+ return policyToDelete;
+ }
+
+ @PreAuthorize("hasRole('POLICY_LIST')")
+ public Set<String> getSyncCorrelationRuleClasses() {
+ return classNamesLoader.getClassNames(ImplementationClassNamesLoader.Type.SYNC_CORRELATION_RULES);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected AbstractPolicyTO resolveReference(final Method method, final Object... args)
+ throws UnresolvedReferenceException {
+ Long id = null;
+
+ if (ArrayUtils.isNotEmpty(args)) {
+ for (int i = 0; id == null && i < args.length; i++) {
+ if (args[i] instanceof Long) {
+ id = (Long) args[i];
+ } else if (args[i] instanceof AbstractPolicyTO) {
+ id = ((AbstractPolicyTO) args[i]).getId();
+ }
+ }
+ }
+
+ if ((id != null) && !id.equals(0l)) {
+ try {
+ return binder.getPolicyTO(policyDAO.find(id));
+ } catch (Throwable ignore) {
+ LOG.debug("Unresolved reference", ignore);
+ throw new UnresolvedReferenceException(ignore);
+ }
+ }
+
+ throw new UnresolvedReferenceException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/ReportLogic.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/ReportLogic.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/ReportLogic.java
new file mode 100644
index 0000000..0d8af57
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/ReportLogic.java
@@ -0,0 +1,348 @@
+/*
+ * 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.server.logic;
+
+import java.io.ByteArrayInputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.ZipInputStream;
+import org.apache.cocoon.optional.pipeline.components.sax.fop.FopSerializer;
+import org.apache.cocoon.pipeline.NonCachingPipeline;
+import org.apache.cocoon.pipeline.Pipeline;
+import org.apache.cocoon.sax.SAXPipelineComponent;
+import org.apache.cocoon.sax.component.XMLGenerator;
+import org.apache.cocoon.sax.component.XMLSerializer;
+import org.apache.cocoon.sax.component.XSLTTransformer;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.report.ReportletConf;
+import org.apache.syncope.common.lib.to.ReportExecTO;
+import org.apache.syncope.common.lib.to.ReportTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.ReportExecExportFormat;
+import org.apache.syncope.common.lib.types.ReportExecStatus;
+import org.apache.syncope.persistence.api.dao.NotFoundException;
+import org.apache.syncope.persistence.api.dao.ReportDAO;
+import org.apache.syncope.persistence.api.dao.ReportExecDAO;
+import org.apache.syncope.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.persistence.api.entity.EntityFactory;
+import org.apache.syncope.persistence.api.entity.Report;
+import org.apache.syncope.persistence.api.entity.ReportExec;
+import org.apache.syncope.server.logic.data.ReportDataBinder;
+import org.apache.syncope.server.logic.init.JobInstanceLoader;
+import org.apache.syncope.server.logic.report.Reportlet;
+import org.apache.syncope.server.logic.report.TextSerializer;
+import org.apache.xmlgraphics.util.MimeConstants;
+import org.quartz.JobKey;
+import org.quartz.Scheduler;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.quartz.SchedulerFactoryBean;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+@Component
+public class ReportLogic extends AbstractTransactionalLogic<ReportTO> {
+
+ @Autowired
+ private ReportDAO reportDAO;
+
+ @Autowired
+ private ReportExecDAO reportExecDAO;
+
+ @Autowired
+ private JobInstanceLoader jobInstanceLoader;
+
+ @Autowired
+ private SchedulerFactoryBean scheduler;
+
+ @Autowired
+ private ReportDataBinder binder;
+
+ @Autowired
+ private EntityFactory entityFactory;
+
+ @PreAuthorize("hasRole('REPORT_CREATE')")
+ public ReportTO create(final ReportTO reportTO) {
+ Report report = entityFactory.newEntity(Report.class);
+ binder.getReport(report, reportTO);
+ report = reportDAO.save(report);
+
+ try {
+ jobInstanceLoader.registerJob(report);
+ } catch (Exception e) {
+ LOG.error("While registering quartz job for report " + report.getKey(), e);
+
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Scheduling);
+ sce.getElements().add(e.getMessage());
+ throw sce;
+ }
+
+ return binder.getReportTO(report);
+ }
+
+ @PreAuthorize("hasRole('REPORT_UPDATE')")
+ public ReportTO update(final ReportTO reportTO) {
+ Report report = reportDAO.find(reportTO.getId());
+ if (report == null) {
+ throw new NotFoundException("Report " + reportTO.getId());
+ }
+
+ binder.getReport(report, reportTO);
+ report = reportDAO.save(report);
+
+ try {
+ jobInstanceLoader.registerJob(report);
+ } catch (Exception e) {
+ LOG.error("While registering quartz job for report " + report.getKey(), e);
+
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Scheduling);
+ sce.getElements().add(e.getMessage());
+ throw sce;
+ }
+
+ return binder.getReportTO(report);
+ }
+
+ @PreAuthorize("hasRole('REPORT_LIST')")
+ public int count() {
+ return reportDAO.count();
+ }
+
+ @PreAuthorize("hasRole('REPORT_LIST')")
+ public List<ReportTO> list(final int page, final int size, final List<OrderByClause> orderByClauses) {
+ List<Report> reports = reportDAO.findAll(page, size, orderByClauses);
+ List<ReportTO> result = new ArrayList<ReportTO>(reports.size());
+ for (Report report : reports) {
+ result.add(binder.getReportTO(report));
+ }
+ return result;
+ }
+
+ @PreAuthorize("hasRole('REPORT_LIST')")
+ @SuppressWarnings("rawtypes")
+ public Set<String> getReportletConfClasses() {
+ Set<String> reportletConfClasses = new HashSet<String>();
+
+ for (Class<Reportlet> reportletClass : binder.getAllReportletClasses()) {
+ Class<? extends ReportletConf> reportletConfClass = binder.getReportletConfClass(reportletClass);
+ if (reportletConfClass != null) {
+ reportletConfClasses.add(reportletConfClass.getName());
+ }
+ }
+
+ return reportletConfClasses;
+ }
+
+ @PreAuthorize("hasRole('REPORT_READ')")
+ public ReportTO read(final Long reportId) {
+ Report report = reportDAO.find(reportId);
+ if (report == null) {
+ throw new NotFoundException("Report " + reportId);
+ }
+ return binder.getReportTO(report);
+ }
+
+ @PreAuthorize("hasRole('REPORT_READ')")
+ @Transactional(readOnly = true)
+ public ReportExecTO readExecution(final Long executionId) {
+ ReportExec reportExec = reportExecDAO.find(executionId);
+ if (reportExec == null) {
+ throw new NotFoundException("Report execution " + executionId);
+ }
+ return binder.getReportExecTO(reportExec);
+ }
+
+ @PreAuthorize("hasRole('REPORT_READ')")
+ public void exportExecutionResult(final OutputStream os, final ReportExec reportExec,
+ final ReportExecExportFormat format) {
+
+ // streaming SAX handler from a compressed byte array stream
+ ByteArrayInputStream bais = new ByteArrayInputStream(reportExec.getExecResult());
+ ZipInputStream zis = new ZipInputStream(bais);
+ try {
+ // a single ZipEntry in the ZipInputStream (see ReportJob)
+ zis.getNextEntry();
+
+ Pipeline<SAXPipelineComponent> pipeline = new NonCachingPipeline<SAXPipelineComponent>();
+ pipeline.addComponent(new XMLGenerator(zis));
+
+ Map<String, Object> parameters = new HashMap<String, Object>();
+ parameters.put("status", reportExec.getStatus());
+ parameters.put("message", reportExec.getMessage());
+ parameters.put("startDate", reportExec.getStartDate());
+ parameters.put("endDate", reportExec.getEndDate());
+
+ switch (format) {
+ case HTML:
+ XSLTTransformer xsl2html = new XSLTTransformer(getClass().getResource("/report/report2html.xsl"));
+ xsl2html.setParameters(parameters);
+ pipeline.addComponent(xsl2html);
+ pipeline.addComponent(XMLSerializer.createXHTMLSerializer());
+ break;
+
+ case PDF:
+ XSLTTransformer xsl2pdf = new XSLTTransformer(getClass().getResource("/report/report2fo.xsl"));
+ xsl2pdf.setParameters(parameters);
+ pipeline.addComponent(xsl2pdf);
+ pipeline.addComponent(new FopSerializer(MimeConstants.MIME_PDF));
+ break;
+
+ case RTF:
+ XSLTTransformer xsl2rtf = new XSLTTransformer(getClass().getResource("/report/report2fo.xsl"));
+ xsl2rtf.setParameters(parameters);
+ pipeline.addComponent(xsl2rtf);
+ pipeline.addComponent(new FopSerializer(MimeConstants.MIME_RTF));
+ break;
+
+ case CSV:
+ XSLTTransformer xsl2csv = new XSLTTransformer(getClass().getResource("/report/report2csv.xsl"));
+ xsl2csv.setParameters(parameters);
+ pipeline.addComponent(xsl2csv);
+ pipeline.addComponent(new TextSerializer());
+ break;
+
+ case XML:
+ default:
+ pipeline.addComponent(XMLSerializer.createXMLSerializer());
+ }
+
+ pipeline.setup(os);
+ pipeline.execute();
+
+ LOG.debug("Result of {} successfully exported as {}", reportExec, format);
+ } catch (Exception e) {
+ LOG.error("While exporting content", e);
+ } finally {
+ IOUtils.closeQuietly(zis);
+ IOUtils.closeQuietly(bais);
+ }
+ }
+
+ @PreAuthorize("hasRole('REPORT_READ')")
+ public ReportExec getAndCheckReportExec(final Long executionId) {
+ ReportExec reportExec = reportExecDAO.find(executionId);
+ if (reportExec == null) {
+ throw new NotFoundException("Report execution " + executionId);
+ }
+ if (!ReportExecStatus.SUCCESS.name().equals(reportExec.getStatus()) || reportExec.getExecResult() == null) {
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidReportExec);
+ sce.getElements().add(reportExec.getExecResult() == null
+ ? "No report data produced"
+ : "Report did not run successfully");
+ throw sce;
+ }
+ return reportExec;
+ }
+
+ @PreAuthorize("hasRole('REPORT_EXECUTE')")
+ public ReportExecTO execute(final Long reportId) {
+ Report report = reportDAO.find(reportId);
+ if (report == null) {
+ throw new NotFoundException("Report " + reportId);
+ }
+
+ try {
+ jobInstanceLoader.registerJob(report);
+
+ scheduler.getScheduler().triggerJob(
+ new JobKey(JobInstanceLoader.getJobName(report), Scheduler.DEFAULT_GROUP));
+ } catch (Exception e) {
+ LOG.error("While executing report {}", report, e);
+
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Scheduling);
+ sce.getElements().add(e.getMessage());
+ throw sce;
+ }
+
+ ReportExecTO result = new ReportExecTO();
+ result.setReport(reportId);
+ result.setStartDate(new Date());
+ result.setStatus(ReportExecStatus.STARTED.name());
+ result.setMessage("Job fired; waiting for results...");
+
+ return result;
+ }
+
+ @PreAuthorize("hasRole('REPORT_DELETE')")
+ public ReportTO delete(final Long reportId) {
+ Report report = reportDAO.find(reportId);
+ if (report == null) {
+ throw new NotFoundException("Report " + reportId);
+ }
+
+ ReportTO deletedReport = binder.getReportTO(report);
+ jobInstanceLoader.unregisterJob(report);
+ reportDAO.delete(report);
+ return deletedReport;
+ }
+
+ @PreAuthorize("hasRole('REPORT_DELETE')")
+ public ReportExecTO deleteExecution(final Long executionId) {
+ ReportExec reportExec = reportExecDAO.find(executionId);
+ if (reportExec == null) {
+ throw new NotFoundException("Report execution " + executionId);
+ }
+
+ ReportExecTO reportExecToDelete = binder.getReportExecTO(reportExec);
+ reportExecDAO.delete(reportExec);
+ return reportExecToDelete;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected ReportTO resolveReference(final Method method, final Object... args)
+ throws UnresolvedReferenceException {
+
+ Long id = null;
+
+ if (ArrayUtils.isNotEmpty(args) && ("create".equals(method.getName())
+ || "update".equals(method.getName())
+ || "delete".equals(method.getName()))) {
+ for (int i = 0; id == null && i < args.length; i++) {
+ if (args[i] instanceof Long) {
+ id = (Long) args[i];
+ } else if (args[i] instanceof ReportTO) {
+ id = ((ReportTO) args[i]).getId();
+ }
+ }
+ }
+
+ if ((id != null) && !id.equals(0l)) {
+ try {
+ return binder.getReportTO(reportDAO.find(id));
+ } catch (Throwable ignore) {
+ LOG.debug("Unresolved reference", ignore);
+ throw new UnresolvedReferenceException(ignore);
+ }
+ }
+
+ throw new UnresolvedReferenceException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/ResourceLogic.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/ResourceLogic.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/ResourceLogic.java
new file mode 100644
index 0000000..d1b2851
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/ResourceLogic.java
@@ -0,0 +1,301 @@
+/*
+ * 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.server.logic;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Set;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.BulkAction;
+import org.apache.syncope.common.lib.to.BulkActionResult;
+import org.apache.syncope.common.lib.to.ConnObjectTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.common.lib.types.SubjectType;
+import org.apache.syncope.persistence.api.dao.ConnInstanceDAO;
+import org.apache.syncope.persistence.api.dao.DuplicateException;
+import org.apache.syncope.persistence.api.dao.ExternalResourceDAO;
+import org.apache.syncope.persistence.api.dao.NotFoundException;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.AttributableUtil;
+import org.apache.syncope.persistence.api.entity.AttributableUtilFactory;
+import org.apache.syncope.persistence.api.entity.ConnInstance;
+import org.apache.syncope.persistence.api.entity.ExternalResource;
+import org.apache.syncope.persistence.api.entity.MappingItem;
+import org.apache.syncope.persistence.api.entity.Subject;
+import org.apache.syncope.provisioning.api.Connector;
+import org.apache.syncope.provisioning.api.ConnectorFactory;
+import org.apache.syncope.server.logic.data.ResourceDataBinder;
+import org.apache.syncope.server.logic.init.ImplementationClassNamesLoader;
+import org.apache.syncope.server.utils.ConnObjectUtil;
+import org.apache.syncope.server.utils.MappingUtil;
+import org.identityconnectors.framework.common.objects.Attribute;
+import org.identityconnectors.framework.common.objects.AttributeUtil;
+import org.identityconnectors.framework.common.objects.ConnectorObject;
+import org.identityconnectors.framework.common.objects.Name;
+import org.identityconnectors.framework.common.objects.ObjectClass;
+import org.identityconnectors.framework.common.objects.Uid;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+@Component
+public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
+
+ @Autowired
+ private ExternalResourceDAO resourceDAO;
+
+ @Autowired
+ private ConnInstanceDAO connInstanceDAO;
+
+ @Autowired
+ private UserDAO userDAO;
+
+ @Autowired
+ private RoleDAO roleDAO;
+
+ @Autowired
+ private ResourceDataBinder binder;
+
+ @Autowired
+ private ImplementationClassNamesLoader classNamesLoader;
+
+ @Autowired
+ private ConnObjectUtil connObjectUtil;
+
+ @Autowired
+ private ConnectorFactory connFactory;
+
+ @Autowired
+ private AttributableUtilFactory attrUtilFactory;
+
+ @PreAuthorize("hasRole('RESOURCE_CREATE')")
+ public ResourceTO create(final ResourceTO resourceTO) {
+ if (StringUtils.isBlank(resourceTO.getKey())) {
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
+ sce.getElements().add("Resource name");
+ throw sce;
+ }
+
+ if (resourceDAO.find(resourceTO.getKey()) != null) {
+ throw new DuplicateException("Resource '" + resourceTO.getKey() + "'");
+ }
+
+ ExternalResource resource = null;
+ try {
+ resource = resourceDAO.save(binder.create(resourceTO));
+ } catch (SyncopeClientException e) {
+ throw e;
+ } catch (Exception e) {
+ SyncopeClientException ex = SyncopeClientException.build(ClientExceptionType.InvalidExternalResource);
+ ex.getElements().add(e.getMessage());
+ throw ex;
+ }
+
+ return binder.getResourceTO(resource);
+ }
+
+ @PreAuthorize("hasRole('RESOURCE_UPDATE')")
+ public ResourceTO update(final ResourceTO resourceTO) {
+ ExternalResource resource = resourceDAO.find(resourceTO.getKey());
+ if (resource == null) {
+ throw new NotFoundException("Resource '" + resourceTO.getKey() + "'");
+ }
+
+ resource = binder.update(resource, resourceTO);
+ try {
+ resource = resourceDAO.save(resource);
+ } catch (SyncopeClientException e) {
+ throw e;
+ } catch (Exception e) {
+ SyncopeClientException ex = SyncopeClientException.build(ClientExceptionType.InvalidExternalResource);
+ ex.getElements().add(e.getMessage());
+ throw ex;
+ }
+
+ return binder.getResourceTO(resource);
+ }
+
+ @PreAuthorize("hasRole('RESOURCE_DELETE')")
+ public ResourceTO delete(final String resourceName) {
+ ExternalResource resource = resourceDAO.find(resourceName);
+ if (resource == null) {
+ throw new NotFoundException("Resource '" + resourceName + "'");
+ }
+
+ ResourceTO resourceToDelete = binder.getResourceTO(resource);
+
+ resourceDAO.delete(resourceName);
+
+ return resourceToDelete;
+ }
+
+ @PreAuthorize("hasRole('RESOURCE_READ')")
+ @Transactional(readOnly = true)
+ public ResourceTO read(final String resourceName) {
+ ExternalResource resource = resourceDAO.find(resourceName);
+ if (resource == null) {
+ throw new NotFoundException("Resource '" + resourceName + "'");
+ }
+
+ return binder.getResourceTO(resource);
+ }
+
+ @PreAuthorize("hasRole('RESOURCE_READ')")
+ public Set<String> getPropagationActionsClasses() {
+ Set<String> actionsClasses = classNamesLoader.getClassNames(
+ ImplementationClassNamesLoader.Type.PROPAGATION_ACTIONS);
+
+ return actionsClasses;
+ }
+
+ @PreAuthorize("isAuthenticated()")
+ @Transactional(readOnly = true)
+ public List<ResourceTO> list(final Long connInstanceId) {
+ List<? extends ExternalResource> resources;
+
+ if (connInstanceId == null) {
+ resources = resourceDAO.findAll();
+ } else {
+ ConnInstance connInstance = connInstanceDAO.find(connInstanceId);
+ resources = connInstance.getResources();
+ }
+
+ return binder.getResourceTOs(resources);
+ }
+
+ @PreAuthorize("hasRole('RESOURCE_GETCONNECTOROBJECT')")
+ @Transactional(readOnly = true)
+ public ConnObjectTO getConnectorObject(final String resourceName, final SubjectType type, final Long id) {
+ ExternalResource resource = resourceDAO.find(resourceName);
+ if (resource == null) {
+ throw new NotFoundException("Resource '" + resourceName + "'");
+ }
+
+ Subject<?, ?, ?> subject = type == SubjectType.USER
+ ? userDAO.find(id)
+ : roleDAO.find(id);
+ if (subject == null) {
+ throw new NotFoundException(type + " " + id);
+ }
+
+ final AttributableUtil attrUtil = attrUtilFactory.getInstance(type.asAttributableType());
+
+ MappingItem accountIdItem = attrUtil.getAccountIdItem(resource);
+ if (accountIdItem == null) {
+ throw new NotFoundException("AccountId mapping for " + type + " " + id + " on resource '" + resourceName
+ + "'");
+ }
+ final String accountIdValue = MappingUtil.getAccountIdValue(
+ subject, resource, attrUtil.getAccountIdItem(resource));
+
+ final ObjectClass objectClass = SubjectType.USER == type ? ObjectClass.ACCOUNT : ObjectClass.GROUP;
+
+ final Connector connector = connFactory.getConnector(resource);
+ final ConnectorObject connectorObject = connector.getObject(objectClass, new Uid(accountIdValue),
+ connector.getOperationOptions(attrUtil.getMappingItems(resource, MappingPurpose.BOTH)));
+ if (connectorObject == null) {
+ throw new NotFoundException("Object " + accountIdValue + " with class " + objectClass
+ + "not found on resource " + resourceName);
+ }
+
+ final Set<Attribute> attributes = connectorObject.getAttributes();
+ if (AttributeUtil.find(Uid.NAME, attributes) == null) {
+ attributes.add(connectorObject.getUid());
+ }
+ if (AttributeUtil.find(Name.NAME, attributes) == null) {
+ attributes.add(connectorObject.getName());
+ }
+
+ return connObjectUtil.getConnObjectTO(connectorObject);
+ }
+
+ @PreAuthorize("hasRole('CONNECTOR_READ')")
+ @Transactional(readOnly = true)
+ public boolean check(final ResourceTO resourceTO) {
+ final ConnInstance connInstance = binder.getConnInstance(resourceTO);
+
+ final Connector connector = connFactory.createConnector(connInstance, connInstance.getConfiguration());
+
+ boolean result;
+ try {
+ connector.test();
+ result = true;
+ } catch (Exception e) {
+ LOG.error("Test connection failure {}", e);
+ result = false;
+ }
+
+ return result;
+ }
+
+ @PreAuthorize("hasRole('RESOURCE_DELETE') and #bulkAction.operation == #bulkAction.operation.DELETE")
+ public BulkActionResult bulk(final BulkAction bulkAction) {
+ BulkActionResult res = new BulkActionResult();
+
+ if (bulkAction.getOperation() == BulkAction.Type.DELETE) {
+ for (String name : bulkAction.getTargets()) {
+ try {
+ res.add(delete(name).getKey(), BulkActionResult.Status.SUCCESS);
+ } catch (Exception e) {
+ LOG.error("Error performing delete for resource {}", name, e);
+ res.add(name, BulkActionResult.Status.FAILURE);
+ }
+ }
+ }
+
+ return res;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected ResourceTO resolveReference(final Method method, final Object... args)
+ throws UnresolvedReferenceException {
+
+ String name = null;
+
+ if (ArrayUtils.isNotEmpty(args)) {
+ for (int i = 0; name == null && i < args.length; i++) {
+ if (args[i] instanceof String) {
+ name = (String) args[i];
+ } else if (args[i] instanceof ResourceTO) {
+ name = ((ResourceTO) args[i]).getKey();
+ }
+ }
+ }
+
+ if (name != null) {
+ try {
+ return binder.getResourceTO(resourceDAO.find(name));
+ } catch (Throwable ignore) {
+ LOG.debug("Unresolved reference", ignore);
+ throw new UnresolvedReferenceException(ignore);
+ }
+ }
+
+ throw new UnresolvedReferenceException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/RoleLogic.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/RoleLogic.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/RoleLogic.java
new file mode 100644
index 0000000..aee0d27
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/RoleLogic.java
@@ -0,0 +1,405 @@
+/*
+ * 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.server.logic;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.Resource;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.mod.RoleMod;
+import org.apache.syncope.common.lib.to.BulkAction;
+import org.apache.syncope.common.lib.to.BulkActionResult;
+import org.apache.syncope.common.lib.to.PropagationStatus;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.SubjectType;
+import org.apache.syncope.persistence.api.RoleEntitlementUtil;
+import org.apache.syncope.persistence.api.dao.NotFoundException;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.dao.SubjectSearchDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.provisioning.api.AttributableTransformer;
+import org.apache.syncope.provisioning.api.RoleProvisioningManager;
+import org.apache.syncope.provisioning.api.propagation.PropagationManager;
+import org.apache.syncope.provisioning.api.propagation.PropagationTaskExecutor;
+import org.apache.syncope.server.logic.data.RoleDataBinder;
+import org.apache.syncope.server.security.AuthContextUtil;
+import org.apache.syncope.server.security.UnauthorizedRoleException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.interceptor.TransactionInterceptor;
+
+/**
+ * Note that this controller does not extend {@link AbstractTransactionalLogic}, hence does not provide any
+ * Spring's Transactional logic at class level.
+ */
+@Component
+public class RoleLogic extends AbstractSubjectLogic<RoleTO, RoleMod> {
+
+ @Autowired
+ protected RoleDAO roleDAO;
+
+ @Autowired
+ protected UserDAO userDAO;
+
+ @Autowired
+ protected SubjectSearchDAO searchDAO;
+
+ @Autowired
+ protected RoleDataBinder binder;
+
+ @Autowired
+ protected PropagationManager propagationManager;
+
+ @Autowired
+ protected PropagationTaskExecutor taskExecutor;
+
+ @Autowired
+ protected AttributableTransformer attrTransformer;
+
+ @Resource(name = "anonymousUser")
+ protected String anonymousUser;
+
+ @Autowired
+ protected RoleProvisioningManager provisioningManager;
+
+ @PreAuthorize("hasAnyRole('ROLE_READ', T(org.apache.syncope.common.lib.SyncopeConstants).ANONYMOUS_ENTITLEMENT)")
+ @Transactional(readOnly = true)
+ @Override
+ public RoleTO read(final Long roleKey) {
+ Role role;
+ // bypass role entitlements check
+ if (anonymousUser.equals(AuthContextUtil.getAuthenticatedUsername())) {
+ role = roleDAO.find(roleKey);
+ } else {
+ role = roleDAO.authFetchRole(roleKey);
+ }
+
+ if (role == null) {
+ throw new NotFoundException("Role " + roleKey);
+ }
+
+ return binder.getRoleTO(role);
+ }
+
+ @PreAuthorize("isAuthenticated() "
+ + "and not(hasRole(T(org.apache.syncope.common.lib.SyncopeConstants).ANONYMOUS_ENTITLEMENT))")
+ @Transactional(readOnly = true)
+ public RoleTO readSelf(final Long roleKey) {
+ // Explicit search instead of using binder.getRoleFromId() in order to bypass auth checks - will do here
+ Role role = roleDAO.find(roleKey);
+ if (role == null) {
+ throw new NotFoundException("Role " + roleKey);
+ }
+
+ Set<Long> ownedRoleIds;
+ User authUser = userDAO.find(AuthContextUtil.getAuthenticatedUsername());
+ if (authUser == null) {
+ ownedRoleIds = Collections.<Long>emptySet();
+ } else {
+ ownedRoleIds = authUser.getRoleIds();
+ }
+
+ Set<Long> allowedRoleIds = RoleEntitlementUtil.getRoleKeys(AuthContextUtil.getOwnedEntitlementNames());
+ allowedRoleIds.addAll(ownedRoleIds);
+ if (!allowedRoleIds.contains(role.getKey())) {
+ throw new UnauthorizedRoleException(role.getKey());
+ }
+
+ return binder.getRoleTO(role);
+ }
+
+ @PreAuthorize("hasRole('ROLE_READ')")
+ @Transactional(readOnly = true)
+ public RoleTO parent(final Long roleKey) {
+ Role role = roleDAO.authFetchRole(roleKey);
+
+ Set<Long> allowedRoleIds = RoleEntitlementUtil.getRoleKeys(AuthContextUtil.getOwnedEntitlementNames());
+ if (role.getParent() != null && !allowedRoleIds.contains(role.getParent().getKey())) {
+ throw new UnauthorizedRoleException(role.getParent().getKey());
+ }
+
+ RoleTO result = role.getParent() == null
+ ? null
+ : binder.getRoleTO(role.getParent());
+
+ return result;
+ }
+
+ @PreAuthorize("hasRole('ROLE_READ')")
+ @Transactional(readOnly = true)
+ public List<RoleTO> children(final Long roleKey) {
+ Role role = roleDAO.authFetchRole(roleKey);
+
+ Set<Long> allowedRoleIds = RoleEntitlementUtil.getRoleKeys(AuthContextUtil.getOwnedEntitlementNames());
+
+ List<Role> children = roleDAO.findChildren(role);
+ List<RoleTO> childrenTOs = new ArrayList<RoleTO>(children.size());
+ for (Role child : children) {
+ if (allowedRoleIds.contains(child.getKey())) {
+ childrenTOs.add(binder.getRoleTO(child));
+ }
+ }
+
+ return childrenTOs;
+ }
+
+ @PreAuthorize("isAuthenticated()")
+ @Transactional(readOnly = true, rollbackFor = { Throwable.class })
+ @Override
+ public int count() {
+ return roleDAO.count();
+ }
+
+ @PreAuthorize("isAuthenticated()")
+ @Transactional(readOnly = true)
+ @Override
+ public List<RoleTO> list(final int page, final int size, final List<OrderByClause> orderBy) {
+ List<Role> roles = roleDAO.findAll(page, size, orderBy);
+
+ List<RoleTO> roleTOs = new ArrayList<>(roles.size());
+ for (Role role : roles) {
+ roleTOs.add(binder.getRoleTO(role));
+ }
+
+ return roleTOs;
+ }
+
+ @PreAuthorize("isAuthenticated()")
+ @Transactional(readOnly = true, rollbackFor = { Throwable.class })
+ @Override
+ public int searchCount(final SearchCond searchCondition) {
+ final Set<Long> adminRoleIds = RoleEntitlementUtil.getRoleKeys(AuthContextUtil.getOwnedEntitlementNames());
+ return searchDAO.count(adminRoleIds, searchCondition, SubjectType.ROLE);
+ }
+
+ @PreAuthorize("isAuthenticated()")
+ @Transactional(readOnly = true, rollbackFor = { Throwable.class })
+ @Override
+ public List<RoleTO> search(final SearchCond searchCondition, final int page, final int size,
+ final List<OrderByClause> orderBy) {
+
+ final List<Role> matchingRoles = searchDAO.search(
+ RoleEntitlementUtil.getRoleKeys(AuthContextUtil.getOwnedEntitlementNames()),
+ searchCondition, page, size, orderBy, SubjectType.ROLE);
+
+ final List<RoleTO> result = new ArrayList<>(matchingRoles.size());
+ for (Role role : matchingRoles) {
+ result.add(binder.getRoleTO(role));
+ }
+
+ return result;
+ }
+
+ @PreAuthorize("hasRole('ROLE_CREATE')")
+ public RoleTO create(final RoleTO roleTO) {
+ // Check that this operation is allowed to be performed by caller
+ Set<Long> allowedRoleIds = RoleEntitlementUtil.getRoleKeys(AuthContextUtil.getOwnedEntitlementNames());
+ if (roleTO.getParent() != 0 && !allowedRoleIds.contains(roleTO.getParent())) {
+ throw new UnauthorizedRoleException(roleTO.getParent());
+ }
+
+ // Attributable transformation (if configured)
+ RoleTO actual = attrTransformer.transform(roleTO);
+ LOG.debug("Transformed: {}", actual);
+
+ /*
+ * Actual operations: workflow, propagation
+ */
+ Map.Entry<Long, List<PropagationStatus>> created = provisioningManager.create(roleTO);
+ final RoleTO savedTO = binder.getRoleTO(created.getKey());
+ savedTO.getPropagationStatusTOs().addAll(created.getValue());
+ return savedTO;
+ }
+
+ @PreAuthorize("hasRole('ROLE_UPDATE')")
+ @Override
+ public RoleTO update(final RoleMod roleMod) {
+ // Check that this operation is allowed to be performed by caller
+ roleDAO.authFetchRole(roleMod.getKey());
+
+ // Attribute value transformation (if configured)
+ RoleMod actual = attrTransformer.transform(roleMod);
+ LOG.debug("Transformed: {}", actual);
+
+ Map.Entry<Long, List<PropagationStatus>> updated = provisioningManager.update(roleMod);
+
+ final RoleTO updatedTO = binder.getRoleTO(updated.getKey());
+ updatedTO.getPropagationStatusTOs().addAll(updated.getValue());
+ return updatedTO;
+ }
+
+ @PreAuthorize("hasRole('ROLE_DELETE')")
+ @Override
+ public RoleTO delete(final Long roleKey) {
+ List<Role> ownedRoles = roleDAO.findOwnedByRole(roleKey);
+ if (!ownedRoles.isEmpty()) {
+ List<String> owned = new ArrayList<String>(ownedRoles.size());
+ for (Role role : ownedRoles) {
+ owned.add(role.getKey() + " " + role.getName());
+ }
+
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.RoleOwnership);
+ sce.getElements().addAll(owned);
+ throw sce;
+ }
+
+ List<PropagationStatus> statuses = provisioningManager.delete(roleKey);
+
+ RoleTO roleTO = new RoleTO();
+ roleTO.setKey(roleKey);
+
+ roleTO.getPropagationStatusTOs().addAll(statuses);
+
+ return roleTO;
+ }
+
+ @PreAuthorize("(hasRole('ROLE_DELETE') and #bulkAction.operation == #bulkAction.operation.DELETE)")
+ public BulkActionResult bulk(final BulkAction bulkAction) {
+ BulkActionResult res = new BulkActionResult();
+
+ if (bulkAction.getOperation() == BulkAction.Type.DELETE) {
+ for (String roleKey : bulkAction.getTargets()) {
+ try {
+ res.add(delete(Long.valueOf(roleKey)).getKey(), BulkActionResult.Status.SUCCESS);
+ } catch (Exception e) {
+ LOG.error("Error performing delete for role {}", roleKey, e);
+ res.add(roleKey, BulkActionResult.Status.FAILURE);
+ }
+ }
+ } else {
+ LOG.warn("Unsupported bulk action: {}", bulkAction.getOperation());
+ }
+
+ return res;
+ }
+
+ @PreAuthorize("hasRole('ROLE_UPDATE')")
+ @Transactional(rollbackFor = { Throwable.class })
+ @Override
+ public RoleTO unlink(final Long roleKey, final Collection<String> resources) {
+ final RoleMod roleMod = new RoleMod();
+ roleMod.setKey(roleKey);
+ roleMod.getResourcesToRemove().addAll(resources);
+ final Long updatedResult = provisioningManager.unlink(roleMod);
+
+ return binder.getRoleTO(updatedResult);
+ }
+
+ @PreAuthorize("hasRole('ROLE_UPDATE')")
+ @Transactional(rollbackFor = { Throwable.class })
+ @Override
+ public RoleTO link(final Long roleKey, final Collection<String> resources) {
+ final RoleMod roleMod = new RoleMod();
+ roleMod.setKey(roleKey);
+ roleMod.getResourcesToAdd().addAll(resources);
+ return binder.getRoleTO(provisioningManager.link(roleMod));
+ }
+
+ @PreAuthorize("hasRole('ROLE_UPDATE')")
+ @Transactional(rollbackFor = { Throwable.class })
+ @Override
+ public RoleTO unassign(final Long roleKey, final Collection<String> resources) {
+ final RoleMod roleMod = new RoleMod();
+ roleMod.setKey(roleKey);
+ roleMod.getResourcesToRemove().addAll(resources);
+ return update(roleMod);
+ }
+
+ @PreAuthorize("hasRole('ROLE_UPDATE')")
+ @Transactional(rollbackFor = { Throwable.class })
+ @Override
+ public RoleTO assign(
+ final Long roleKey, final Collection<String> resources, final boolean changePwd, final String password) {
+
+ final RoleMod userMod = new RoleMod();
+ userMod.setKey(roleKey);
+ userMod.getResourcesToAdd().addAll(resources);
+ return update(userMod);
+ }
+
+ @PreAuthorize("hasRole('ROLE_UPDATE')")
+ @Transactional(rollbackFor = { Throwable.class })
+ @Override
+ public RoleTO deprovision(final Long roleKey, final Collection<String> resources) {
+ final Role role = roleDAO.authFetchRole(roleKey);
+
+ List<PropagationStatus> statuses = provisioningManager.deprovision(roleKey, resources);
+
+ final RoleTO updatedTO = binder.getRoleTO(role);
+ updatedTO.getPropagationStatusTOs().addAll(statuses);
+ return updatedTO;
+ }
+
+ @PreAuthorize("hasRole('ROLE_UPDATE')")
+ @Transactional(rollbackFor = { Throwable.class })
+ @Override
+ public RoleTO provision(
+ final Long roleKey, final Collection<String> resources, final boolean changePwd, final String password) {
+ final RoleTO original = binder.getRoleTO(roleKey);
+
+ //trick: assign and retrieve propagation statuses ...
+ original.getPropagationStatusTOs().addAll(
+ assign(roleKey, resources, changePwd, password).getPropagationStatusTOs());
+
+ // .... rollback.
+ TransactionInterceptor.currentTransactionStatus().setRollbackOnly();
+ return original;
+ }
+
+ @Override
+ protected RoleTO resolveReference(final Method method, final Object... args) throws UnresolvedReferenceException {
+ Long id = null;
+
+ if (ArrayUtils.isNotEmpty(args)) {
+ for (int i = 0; id == null && i < args.length; i++) {
+ if (args[i] instanceof Long) {
+ id = (Long) args[i];
+ } else if (args[i] instanceof RoleTO) {
+ id = ((RoleTO) args[i]).getKey();
+ } else if (args[i] instanceof RoleMod) {
+ id = ((RoleMod) args[i]).getKey();
+ }
+ }
+ }
+
+ if ((id != null) && !id.equals(0l)) {
+ try {
+ return binder.getRoleTO(id);
+ } catch (Throwable ignore) {
+ LOG.debug("Unresolved reference", ignore);
+ throw new UnresolvedReferenceException(ignore);
+ }
+ }
+
+ throw new UnresolvedReferenceException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/SchemaLogic.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/SchemaLogic.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/SchemaLogic.java
new file mode 100644
index 0000000..675bd42
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/SchemaLogic.java
@@ -0,0 +1,328 @@
+/*
+ * 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.server.logic;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AbstractSchemaTO;
+import org.apache.syncope.common.lib.to.DerSchemaTO;
+import org.apache.syncope.common.lib.to.PlainSchemaTO;
+import org.apache.syncope.common.lib.to.VirSchemaTO;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.persistence.api.dao.DerSchemaDAO;
+import org.apache.syncope.persistence.api.dao.DuplicateException;
+import org.apache.syncope.persistence.api.dao.NotFoundException;
+import org.apache.syncope.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.persistence.api.dao.VirSchemaDAO;
+import org.apache.syncope.persistence.api.entity.AttributableUtil;
+import org.apache.syncope.persistence.api.entity.AttributableUtilFactory;
+import org.apache.syncope.persistence.api.entity.DerSchema;
+import org.apache.syncope.persistence.api.entity.PlainSchema;
+import org.apache.syncope.persistence.api.entity.VirSchema;
+import org.apache.syncope.server.logic.data.SchemaDataBinder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SchemaLogic extends AbstractTransactionalLogic<AbstractSchemaTO> {
+
+ @Autowired
+ private PlainSchemaDAO plainSchemaDAO;
+
+ @Autowired
+ private DerSchemaDAO derSchemaDAO;
+
+ @Autowired
+ private VirSchemaDAO virSchemaDAO;
+
+ @Autowired
+ private SchemaDataBinder binder;
+
+ @Autowired
+ private AttributableUtilFactory attrUtilFactory;
+
+ private boolean doesSchemaExist(final SchemaType schemaType, final String name, final AttributableUtil attrUtil) {
+ boolean found;
+
+ switch (schemaType) {
+ case VIRTUAL:
+ found = virSchemaDAO.find(name, attrUtil.virSchemaClass()) != null;
+ break;
+
+ case DERIVED:
+ found = derSchemaDAO.find(name, attrUtil.derSchemaClass()) != null;
+ break;
+
+ case PLAIN:
+ found = plainSchemaDAO.find(name, attrUtil.plainSchemaClass()) != null;
+ break;
+
+ default:
+ found = false;
+ }
+
+ return found;
+ }
+
+ @PreAuthorize("hasRole('SCHEMA_CREATE')")
+ @SuppressWarnings("unchecked")
+ public <T extends AbstractSchemaTO> T create(
+ final AttributableType attrType, final SchemaType schemaType, final T schemaTO) {
+
+ if (StringUtils.isBlank(schemaTO.getKey())) {
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
+ sce.getElements().add("Schema name");
+ throw sce;
+ }
+
+ final AttributableUtil attrUtil = attrUtilFactory.getInstance(attrType);
+
+ if (doesSchemaExist(schemaType, schemaTO.getKey(), attrUtil)) {
+ throw new DuplicateException(schemaType + "/" + attrType + "/" + schemaTO.getKey());
+ }
+
+ T created;
+ switch (schemaType) {
+ case VIRTUAL:
+ VirSchema virSchema = attrUtil.newVirSchema();
+ binder.create((VirSchemaTO) schemaTO, virSchema);
+ virSchema = virSchemaDAO.save(virSchema);
+ created = (T) binder.getVirSchemaTO(virSchema);
+ break;
+ case DERIVED:
+ DerSchema derSchema = attrUtil.newDerSchema();
+ binder.create((DerSchemaTO) schemaTO, derSchema);
+ derSchema = derSchemaDAO.save(derSchema);
+
+ created = (T) binder.getDerSchemaTO(derSchema);
+ break;
+
+ case PLAIN:
+ default:
+ PlainSchema normalSchema = attrUtil.newPlainSchema();
+ binder.create((PlainSchemaTO) schemaTO, normalSchema);
+ normalSchema = plainSchemaDAO.save(normalSchema);
+
+ created = (T) binder.getSchemaTO(normalSchema, attrUtil);
+ }
+ return created;
+ }
+
+ @PreAuthorize("hasRole('SCHEMA_DELETE')")
+ public void delete(final AttributableType attrType, final SchemaType schemaType, final String schemaName) {
+ final AttributableUtil attrUtil = attrUtilFactory.getInstance(attrType);
+
+ if (!doesSchemaExist(schemaType, schemaName, attrUtil)) {
+ throw new NotFoundException(schemaType + "/" + attrType + "/" + schemaName);
+ }
+
+ switch (schemaType) {
+ case VIRTUAL:
+ virSchemaDAO.delete(schemaName, attrUtil);
+ break;
+
+ case DERIVED:
+ derSchemaDAO.delete(schemaName, attrUtil);
+ break;
+
+ case PLAIN:
+ default:
+ plainSchemaDAO.delete(schemaName, attrUtil);
+ }
+ }
+
+ @PreAuthorize("isAuthenticated()")
+ @SuppressWarnings("unchecked")
+ public <T extends AbstractSchemaTO> List<T> list(final AttributableType attrType, final SchemaType schemaType) {
+ final AttributableUtil attrUtil = attrUtilFactory.getInstance(attrType);
+
+ List<T> result;
+ switch (schemaType) {
+ case VIRTUAL:
+ List<VirSchema> virSchemas = virSchemaDAO.findAll(attrUtil.virSchemaClass());
+ result = new ArrayList<>(virSchemas.size());
+ for (VirSchema derSchema : virSchemas) {
+ result.add((T) binder.getVirSchemaTO(derSchema));
+ }
+ break;
+
+ case DERIVED:
+ List<DerSchema> derSchemas = derSchemaDAO.findAll(attrUtil.derSchemaClass());
+ result = new ArrayList<>(derSchemas.size());
+ for (DerSchema derSchema : derSchemas) {
+ result.add((T) binder.getDerSchemaTO(derSchema));
+ }
+ break;
+
+ case PLAIN:
+ default:
+ List<PlainSchema> schemas = plainSchemaDAO.findAll(attrUtil.plainSchemaClass());
+ result = new ArrayList<>(schemas.size());
+ for (PlainSchema schema : schemas) {
+ result.add((T) binder.getSchemaTO(schema, attrUtil));
+ }
+ }
+
+ return result;
+ }
+
+ @PreAuthorize("hasRole('SCHEMA_READ')")
+ @SuppressWarnings("unchecked")
+ public <T extends AbstractSchemaTO> T read(
+ final AttributableType attrType, final SchemaType schemaType, final String schemaName) {
+
+ final AttributableUtil attrUtil = attrUtilFactory.getInstance(attrType);
+
+ T read;
+ switch (schemaType) {
+ case VIRTUAL:
+ VirSchema virSchema = virSchemaDAO.find(schemaName, attrUtil.virSchemaClass());
+ if (virSchema == null) {
+ throw new NotFoundException("Virtual Schema '" + schemaName + "'");
+ }
+
+ read = (T) binder.getVirSchemaTO(virSchema);
+ break;
+
+ case DERIVED:
+ DerSchema derSchema = derSchemaDAO.find(schemaName, attrUtil.derSchemaClass());
+ if (derSchema == null) {
+ throw new NotFoundException("Derived schema '" + schemaName + "'");
+ }
+
+ read = (T) binder.getDerSchemaTO(derSchema);
+ break;
+
+ case PLAIN:
+ default:
+ PlainSchema schema = plainSchemaDAO.find(schemaName, attrUtil.plainSchemaClass());
+ if (schema == null) {
+ throw new NotFoundException("Schema '" + schemaName + "'");
+ }
+
+ read = (T) binder.getSchemaTO(schema, attrUtil);
+ }
+
+ return read;
+ }
+
+ @PreAuthorize("hasRole('SCHEMA_UPDATE')")
+ public <T extends AbstractSchemaTO> void update(
+ final AttributableType attrType, final SchemaType schemaType, final T schemaTO) {
+
+ final AttributableUtil attrUtil = attrUtilFactory.getInstance(attrType);
+
+ if (!doesSchemaExist(schemaType, schemaTO.getKey(), attrUtil)) {
+ throw new NotFoundException(schemaType + "/" + attrType + "/" + schemaTO.getKey());
+ }
+
+ switch (schemaType) {
+ case VIRTUAL:
+ VirSchema virSchema = virSchemaDAO.find(schemaTO.getKey(), attrUtil.virSchemaClass());
+ if (virSchema == null) {
+ throw new NotFoundException("Virtual Schema '" + schemaTO.getKey() + "'");
+ }
+
+ binder.update((VirSchemaTO) schemaTO, virSchema);
+ virSchemaDAO.save(virSchema);
+ break;
+
+ case DERIVED:
+ DerSchema derSchema = derSchemaDAO.find(schemaTO.getKey(), attrUtil.derSchemaClass());
+ if (derSchema == null) {
+ throw new NotFoundException("Derived schema '" + schemaTO.getKey() + "'");
+ }
+
+ binder.update((DerSchemaTO) schemaTO, derSchema);
+ derSchemaDAO.save(derSchema);
+ break;
+
+ case PLAIN:
+ default:
+ PlainSchema schema = plainSchemaDAO.find(schemaTO.getKey(), attrUtil.plainSchemaClass());
+ if (schema == null) {
+ throw new NotFoundException("Schema '" + schemaTO.getKey() + "'");
+ }
+
+ binder.update((PlainSchemaTO) schemaTO, schema, attrUtil);
+ plainSchemaDAO.save(schema);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected AbstractSchemaTO resolveReference(final Method method, final Object... args)
+ throws UnresolvedReferenceException {
+
+ String kind = null;
+ String name = null;
+ if (ArrayUtils.isNotEmpty(args)) {
+ for (int i = 0; (name == null || kind == null) && i < args.length; i++) {
+ if (args[i] instanceof String) {
+ if (kind == null) {
+ kind = (String) args[i];
+ } else {
+ name = (String) args[i];
+ }
+ } else if (args[i] instanceof AbstractSchemaTO) {
+ name = ((AbstractSchemaTO) args[i]).getKey();
+ }
+ }
+ }
+
+ if (name != null) {
+ try {
+ final AttributableUtil attrUtil = attrUtilFactory.getInstance(kind);
+
+ AbstractSchemaTO result = null;
+
+ PlainSchema plainSchema = plainSchemaDAO.find(name, attrUtil.plainSchemaClass());
+ if (plainSchema == null) {
+ DerSchema derSchema = derSchemaDAO.find(name, attrUtil.derSchemaClass());
+ if (derSchema == null) {
+ VirSchema virSchema = virSchemaDAO.find(name, attrUtil.virSchemaClass());
+ if (virSchema != null) {
+ result = binder.getVirSchemaTO(virSchema);
+ }
+ } else {
+ result = binder.getDerSchemaTO(derSchema);
+ }
+ } else {
+ result = binder.getSchemaTO(plainSchema, attrUtil);
+ }
+
+ return result;
+ } catch (Throwable ignore) {
+ LOG.debug("Unresolved reference", ignore);
+ throw new UnresolvedReferenceException(ignore);
+ }
+ }
+
+ throw new UnresolvedReferenceException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/SecurityQuestionLogic.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/SecurityQuestionLogic.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/SecurityQuestionLogic.java
new file mode 100644
index 0000000..01b2a57
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/SecurityQuestionLogic.java
@@ -0,0 +1,150 @@
+/*
+ * 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.server.logic;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.syncope.common.lib.to.SecurityQuestionTO;
+import org.apache.syncope.persistence.api.dao.NotFoundException;
+import org.apache.syncope.persistence.api.dao.SecurityQuestionDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.entity.user.SecurityQuestion;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.server.logic.data.SecurityQuestionDataBinder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SecurityQuestionLogic extends AbstractTransactionalLogic<SecurityQuestionTO> {
+
+ @Autowired
+ private SecurityQuestionDAO securityQuestionDAO;
+
+ @Autowired
+ private UserDAO userDAO;
+
+ @Autowired
+ private SecurityQuestionDataBinder binder;
+
+ @PreAuthorize("isAuthenticated()")
+ public List<SecurityQuestionTO> list() {
+ List<SecurityQuestionTO> result = new ArrayList<SecurityQuestionTO>();
+ for (SecurityQuestion securityQuestion : securityQuestionDAO.findAll()) {
+ result.add(binder.getSecurityQuestionTO(securityQuestion));
+ }
+
+ return result;
+ }
+
+ @PreAuthorize("isAuthenticated()")
+ public SecurityQuestionTO read(final Long securityQuestionId) {
+ SecurityQuestion securityQuestion = securityQuestionDAO.find(securityQuestionId);
+ if (securityQuestion == null) {
+ LOG.error("Could not find security question '" + securityQuestionId + "'");
+
+ throw new NotFoundException(String.valueOf(securityQuestionId));
+ }
+
+ return binder.getSecurityQuestionTO(securityQuestion);
+ }
+
+ @PreAuthorize("hasRole('SECURITY_QUESTION_CREATE')")
+ public SecurityQuestionTO create(final SecurityQuestionTO securityQuestionTO) {
+ return binder.getSecurityQuestionTO(securityQuestionDAO.save(binder.create(securityQuestionTO)));
+ }
+
+ @PreAuthorize("hasRole('SECURITY_QUESTION_UPDATE')")
+ public SecurityQuestionTO update(final SecurityQuestionTO securityQuestionTO) {
+ SecurityQuestion securityQuestion = securityQuestionDAO.find(securityQuestionTO.getKey());
+ if (securityQuestion == null) {
+ LOG.error("Could not find security question '" + securityQuestionTO.getKey() + "'");
+
+ throw new NotFoundException(String.valueOf(securityQuestionTO.getKey()));
+ }
+
+ binder.update(securityQuestion, securityQuestionTO);
+ securityQuestion = securityQuestionDAO.save(securityQuestion);
+
+ return binder.getSecurityQuestionTO(securityQuestion);
+ }
+
+ @PreAuthorize("hasRole('SECURITY_QUESTION_DELETE')")
+ public SecurityQuestionTO delete(final Long securityQuestionId) {
+ SecurityQuestion securityQuestion = securityQuestionDAO.find(securityQuestionId);
+ if (securityQuestion == null) {
+ LOG.error("Could not find security question '" + securityQuestionId + "'");
+
+ throw new NotFoundException(String.valueOf(securityQuestionId));
+ }
+
+ SecurityQuestionTO deleted = binder.getSecurityQuestionTO(securityQuestion);
+ securityQuestionDAO.delete(securityQuestionId);
+ return deleted;
+ }
+
+ @PreAuthorize("isAnonymous() or hasRole(T(org.apache.syncope.common.lib.SyncopeConstants).ANONYMOUS_ENTITLEMENT)")
+ public SecurityQuestionTO read(final String username) {
+ if (username == null) {
+ throw new NotFoundException("Null username");
+ }
+ User user = userDAO.find(username);
+ if (user == null) {
+ throw new NotFoundException("User " + username);
+ }
+
+ if (user.getSecurityQuestion() == null) {
+ LOG.error("Could not find security question for user '" + username + "'");
+
+ throw new NotFoundException("Security question for user " + username);
+ }
+
+ return binder.getSecurityQuestionTO(user.getSecurityQuestion());
+ }
+
+ @Override
+ protected SecurityQuestionTO resolveReference(final Method method, final Object... args)
+ throws UnresolvedReferenceException {
+
+ Long id = null;
+
+ if (ArrayUtils.isNotEmpty(args)) {
+ for (int i = 0; id == null && i < args.length; i++) {
+ if (args[i] instanceof Long) {
+ id = (Long) args[i];
+ } else if (args[i] instanceof SecurityQuestionTO) {
+ id = ((SecurityQuestionTO) args[i]).getKey();
+ }
+ }
+ }
+
+ if ((id != null) && !id.equals(0l)) {
+ try {
+ return binder.getSecurityQuestionTO(securityQuestionDAO.find(id));
+ } catch (Throwable ignore) {
+ LOG.debug("Unresolved reference", ignore);
+ throw new UnresolvedReferenceException(ignore);
+ }
+ }
+
+ throw new UnresolvedReferenceException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/TaskLogic.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/TaskLogic.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/TaskLogic.java
new file mode 100644
index 0000000..11c9b4b
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/TaskLogic.java
@@ -0,0 +1,408 @@
+/*
+ * 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.server.logic;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.BulkAction;
+import org.apache.syncope.common.lib.to.BulkActionResult;
+import org.apache.syncope.common.lib.to.SchedTaskTO;
+import org.apache.syncope.common.lib.to.SyncTaskTO;
+import org.apache.syncope.common.lib.to.TaskExecTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.PropagationMode;
+import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.persistence.api.dao.NotFoundException;
+import org.apache.syncope.persistence.api.dao.TaskDAO;
+import org.apache.syncope.persistence.api.dao.TaskExecDAO;
+import org.apache.syncope.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.persistence.api.entity.task.NotificationTask;
+import org.apache.syncope.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.persistence.api.entity.task.SchedTask;
+import org.apache.syncope.persistence.api.entity.task.Task;
+import org.apache.syncope.persistence.api.entity.task.TaskExec;
+import org.apache.syncope.persistence.api.entity.task.TaskUtil;
+import org.apache.syncope.persistence.api.entity.task.TaskUtilFactory;
+import org.apache.syncope.provisioning.api.job.TaskJob;
+import org.apache.syncope.provisioning.api.propagation.PropagationTaskExecutor;
+import org.apache.syncope.server.logic.data.TaskDataBinder;
+import org.apache.syncope.server.logic.init.ImplementationClassNamesLoader;
+import org.apache.syncope.server.logic.init.JobInstanceLoader;
+import org.apache.syncope.server.logic.notification.NotificationJob;
+import org.quartz.JobDataMap;
+import org.quartz.JobKey;
+import org.quartz.Scheduler;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.quartz.SchedulerFactoryBean;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class TaskLogic extends AbstractTransactionalLogic<AbstractTaskTO> {
+
+ @Autowired
+ private TaskDAO taskDAO;
+
+ @Autowired
+ private TaskExecDAO taskExecDAO;
+
+ @Autowired
+ private TaskDataBinder binder;
+
+ @Autowired
+ private PropagationTaskExecutor taskExecutor;
+
+ @Autowired
+ private NotificationJob notificationJob;
+
+ @Autowired
+ private JobInstanceLoader jobInstanceLoader;
+
+ @Autowired
+ private SchedulerFactoryBean scheduler;
+
+ @Autowired
+ private ImplementationClassNamesLoader classNamesLoader;
+
+ @Autowired
+ private TaskUtilFactory taskUtilFactory;
+
+ @PreAuthorize("hasRole('TASK_CREATE')")
+ public <T extends SchedTaskTO> T createSchedTask(final T taskTO) {
+ TaskUtil taskUtil = taskUtilFactory.getInstance(taskTO);
+
+ SchedTask task = binder.createSchedTask(taskTO, taskUtil);
+ task = taskDAO.save(task);
+
+ try {
+ jobInstanceLoader.registerJob(task, task.getJobClassName(), task.getCronExpression());
+ } catch (Exception e) {
+ LOG.error("While registering quartz job for task " + task.getKey(), e);
+
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Scheduling);
+ sce.getElements().add(e.getMessage());
+ throw sce;
+ }
+
+ return binder.getTaskTO(task, taskUtil);
+ }
+
+ @PreAuthorize("hasRole('TASK_UPDATE')")
+ public SyncTaskTO updateSync(final SyncTaskTO taskTO) {
+ return updateSched(taskTO);
+ }
+
+ @PreAuthorize("hasRole('TASK_UPDATE')")
+ public <T extends SchedTaskTO> T updateSched(final SchedTaskTO taskTO) {
+ SchedTask task = taskDAO.find(taskTO.getId());
+ if (task == null) {
+ throw new NotFoundException("Task " + taskTO.getId());
+ }
+
+ TaskUtil taskUtil = taskUtilFactory.getInstance(task);
+
+ binder.updateSchedTask(task, taskTO, taskUtil);
+ task = taskDAO.save(task);
+
+ try {
+ jobInstanceLoader.registerJob(task, task.getJobClassName(), task.getCronExpression());
+ } catch (Exception e) {
+ LOG.error("While registering quartz job for task " + task.getKey(), e);
+
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Scheduling);
+ sce.getElements().add(e.getMessage());
+ throw sce;
+ }
+
+ return binder.getTaskTO(task, taskUtil);
+ }
+
+ @PreAuthorize("hasRole('TASK_LIST')")
+ public int count(final TaskType taskType) {
+ return taskDAO.count(taskType);
+ }
+
+ @PreAuthorize("hasRole('TASK_LIST')")
+ @SuppressWarnings("unchecked")
+ public <T extends AbstractTaskTO> List<T> list(final TaskType taskType,
+ final int page, final int size, final List<OrderByClause> orderByClauses) {
+
+ TaskUtil taskUtil = taskUtilFactory.getInstance(taskType);
+
+ List<Task> tasks = taskDAO.findAll(page, size, orderByClauses, taskType);
+ List<T> taskTOs = new ArrayList<>(tasks.size());
+ for (Task task : tasks) {
+ taskTOs.add((T) binder.getTaskTO(task, taskUtil));
+ }
+
+ return taskTOs;
+ }
+
+ @PreAuthorize("hasRole('TASK_LIST')")
+ public Set<String> getJobClasses() {
+ return classNamesLoader.getClassNames(ImplementationClassNamesLoader.Type.TASKJOB);
+ }
+
+ @PreAuthorize("hasRole('TASK_LIST')")
+ public Set<String> getSyncActionsClasses() {
+ return classNamesLoader.getClassNames(ImplementationClassNamesLoader.Type.SYNC_ACTIONS);
+ }
+
+ @PreAuthorize("hasRole('TASK_LIST')")
+ public Set<String> getPushActionsClasses() {
+ return classNamesLoader.getClassNames(ImplementationClassNamesLoader.Type.PUSH_ACTIONS);
+ }
+
+ @PreAuthorize("hasRole('TASK_READ')")
+ public <T extends AbstractTaskTO> T read(final Long taskId) {
+ Task task = taskDAO.find(taskId);
+ if (task == null) {
+ throw new NotFoundException("Task " + taskId);
+ }
+ return binder.getTaskTO(task, taskUtilFactory.getInstance(task));
+ }
+
+ @PreAuthorize("hasRole('TASK_READ')")
+ public TaskExecTO readExecution(final Long executionId) {
+ TaskExec taskExec = taskExecDAO.find(executionId);
+ if (taskExec == null) {
+ throw new NotFoundException("Task execution " + executionId);
+ }
+ return binder.getTaskExecTO(taskExec);
+ }
+
+ @PreAuthorize("hasRole('TASK_EXECUTE')")
+ public TaskExecTO execute(final Long taskId, final boolean dryRun) {
+ Task task = taskDAO.find(taskId);
+ if (task == null) {
+ throw new NotFoundException("Task " + taskId);
+ }
+ TaskUtil taskUtil = taskUtilFactory.getInstance(task);
+
+ TaskExecTO result = null;
+ switch (taskUtil.getType()) {
+ case PROPAGATION:
+ final TaskExec propExec = taskExecutor.execute((PropagationTask) task);
+ result = binder.getTaskExecTO(propExec);
+ break;
+
+ case NOTIFICATION:
+ final TaskExec notExec = notificationJob.executeSingle((NotificationTask) task);
+ result = binder.getTaskExecTO(notExec);
+ break;
+
+ case SCHEDULED:
+ case SYNCHRONIZATION:
+ case PUSH:
+ try {
+ jobInstanceLoader.registerJob(task,
+ ((SchedTask) task).getJobClassName(),
+ ((SchedTask) task).getCronExpression());
+
+ JobDataMap map = new JobDataMap();
+ map.put(TaskJob.DRY_RUN_JOBDETAIL_KEY, dryRun);
+
+ scheduler.getScheduler().triggerJob(
+ new JobKey(JobInstanceLoader.getJobName(task), Scheduler.DEFAULT_GROUP), map);
+ } catch (Exception e) {
+ LOG.error("While executing task {}", task, e);
+
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Scheduling);
+ sce.getElements().add(e.getMessage());
+ throw sce;
+ }
+
+ result = new TaskExecTO();
+ result.setTask(taskId);
+ result.setStartDate(new Date());
+ result.setStatus("JOB_FIRED");
+ result.setMessage("Job fired; waiting for results...");
+ break;
+
+ default:
+ }
+
+ return result;
+ }
+
+ @PreAuthorize("hasRole('TASK_READ')")
+ public TaskExecTO report(final Long executionId, final PropagationTaskExecStatus status, final String message) {
+ TaskExec exec = taskExecDAO.find(executionId);
+ if (exec == null) {
+ throw new NotFoundException("Task execution " + executionId);
+ }
+
+ SyncopeClientException sce = SyncopeClientException.build(
+ ClientExceptionType.InvalidPropagationTaskExecReport);
+
+ TaskUtil taskUtil = taskUtilFactory.getInstance(exec.getTask());
+ if (TaskType.PROPAGATION == taskUtil.getType()) {
+ PropagationTask task = (PropagationTask) exec.getTask();
+ if (task.getPropagationMode() != PropagationMode.TWO_PHASES) {
+ sce.getElements().add("Propagation mode: " + task.getPropagationMode());
+ }
+ } else {
+ sce.getElements().add("Task type: " + taskUtil);
+ }
+
+ switch (status) {
+ case SUCCESS:
+ case FAILURE:
+ break;
+
+ case CREATED:
+ case SUBMITTED:
+ case UNSUBMITTED:
+ sce.getElements().add("Execution status to be set: " + status);
+ break;
+
+ default:
+ }
+
+ if (!sce.isEmpty()) {
+ throw sce;
+ }
+
+ exec.setStatus(status.toString());
+ exec.setMessage(message);
+ return binder.getTaskExecTO(taskExecDAO.save(exec));
+ }
+
+ @PreAuthorize("hasRole('TASK_DELETE')")
+ public <T extends AbstractTaskTO> T delete(final Long taskId) {
+ Task task = taskDAO.find(taskId);
+ if (task == null) {
+ throw new NotFoundException("Task " + taskId);
+ }
+ TaskUtil taskUtil = taskUtilFactory.getInstance(task);
+
+ T taskToDelete = binder.getTaskTO(task, taskUtil);
+
+ if (TaskType.SCHEDULED == taskUtil.getType()
+ || TaskType.SYNCHRONIZATION == taskUtil.getType()
+ || TaskType.PUSH == taskUtil.getType()) {
+ jobInstanceLoader.unregisterJob(task);
+ }
+
+ taskDAO.delete(task);
+ return taskToDelete;
+ }
+
+ @PreAuthorize("hasRole('TASK_DELETE')")
+ public TaskExecTO deleteExecution(final Long executionId) {
+ TaskExec taskExec = taskExecDAO.find(executionId);
+ if (taskExec == null) {
+ throw new NotFoundException("Task execution " + executionId);
+ }
+
+ TaskExecTO taskExecutionToDelete = binder.getTaskExecTO(taskExec);
+ taskExecDAO.delete(taskExec);
+ return taskExecutionToDelete;
+ }
+
+ @PreAuthorize("(hasRole('TASK_DELETE') and #bulkAction.operation == #bulkAction.operation.DELETE) or "
+ + "(hasRole('TASK_EXECUTE') and "
+ + "(#bulkAction.operation == #bulkAction.operation.EXECUTE or "
+ + "#bulkAction.operation == #bulkAction.operation.DRYRUN))")
+ public BulkActionResult bulk(final BulkAction bulkAction) {
+ BulkActionResult res = new BulkActionResult();
+
+ switch (bulkAction.getOperation()) {
+ case DELETE:
+ for (String taskId : bulkAction.getTargets()) {
+ try {
+ res.add(delete(Long.valueOf(taskId)).getId(), BulkActionResult.Status.SUCCESS);
+ } catch (Exception e) {
+ LOG.error("Error performing delete for task {}", taskId, e);
+ res.add(taskId, BulkActionResult.Status.FAILURE);
+ }
+ }
+ break;
+
+ case DRYRUN:
+ for (String taskId : bulkAction.getTargets()) {
+ try {
+ execute(Long.valueOf(taskId), true);
+ res.add(taskId, BulkActionResult.Status.SUCCESS);
+ } catch (Exception e) {
+ LOG.error("Error performing dryrun for task {}", taskId, e);
+ res.add(taskId, BulkActionResult.Status.FAILURE);
+ }
+ }
+ break;
+
+ case EXECUTE:
+ for (String taskId : bulkAction.getTargets()) {
+ try {
+ execute(Long.valueOf(taskId), false);
+ res.add(taskId, BulkActionResult.Status.SUCCESS);
+ } catch (Exception e) {
+ LOG.error("Error performing execute for task {}", taskId, e);
+ res.add(taskId, BulkActionResult.Status.FAILURE);
+ }
+ }
+ break;
+
+ default:
+ }
+
+ return res;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected AbstractTaskTO resolveReference(final Method method, final Object... args)
+ throws UnresolvedReferenceException {
+
+ Long id = null;
+
+ if (ArrayUtils.isNotEmpty(args)
+ && !"deleteExecution".equals(method.getName()) && !"readExecution".equals(method.getName())) {
+
+ for (int i = 0; id == null && i < args.length; i++) {
+ if (args[i] instanceof Long) {
+ id = (Long) args[i];
+ } else if (args[i] instanceof AbstractTaskTO) {
+ id = ((AbstractTaskTO) args[i]).getId();
+ }
+ }
+ }
+
+ if ((id != null) && !id.equals(0l)) {
+ try {
+ final Task task = taskDAO.find(id);
+ return binder.getTaskTO(task, taskUtilFactory.getInstance(task));
+ } catch (Throwable ignore) {
+ LOG.debug("Unresolved reference", ignore);
+ throw new UnresolvedReferenceException(ignore);
+ }
+ }
+
+ throw new UnresolvedReferenceException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/UnresolvedReferenceException.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/UnresolvedReferenceException.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/UnresolvedReferenceException.java
new file mode 100644
index 0000000..aff28d9
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/UnresolvedReferenceException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.server.logic;
+
+/**
+ * Indicates unresolved bean reference.
+ */
+public class UnresolvedReferenceException extends Exception {
+
+ private static final long serialVersionUID = -675489116009955632L;
+
+ public UnresolvedReferenceException() {
+ super();
+ }
+
+ public UnresolvedReferenceException(final Throwable cause) {
+ super(cause);
+ }
+}