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/02/12 10:14:25 UTC
[20/54] [abbrv] [partial] syncope git commit: [SYNCOPE-620] Renaming
'server' after 'core',
to provide continuity with older releases (especially for archetype)
http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ReportDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ReportDataBinderImpl.java b/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ReportDataBinderImpl.java
new file mode 100644
index 0000000..e98bc7d
--- /dev/null
+++ b/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ReportDataBinderImpl.java
@@ -0,0 +1,142 @@
+/*
+ * 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.provisioning.java.data;
+
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.syncope.core.provisioning.api.data.ReportDataBinder;
+import org.apache.syncope.common.lib.report.AbstractReportletConf;
+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.core.persistence.api.dao.ReportExecDAO;
+import org.apache.syncope.core.persistence.api.entity.Report;
+import org.apache.syncope.core.persistence.api.entity.ReportExec;
+import org.apache.syncope.core.provisioning.api.job.JobNamer;
+import org.apache.syncope.core.misc.spring.BeanUtils;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.Trigger;
+import org.quartz.TriggerKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.quartz.SchedulerFactoryBean;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ReportDataBinderImpl implements ReportDataBinder {
+
+ /**
+ * Logger.
+ */
+ private static final Logger LOG = LoggerFactory.getLogger(ReportDataBinder.class);
+
+ private static final String[] IGNORE_REPORT_PROPERTIES = { "key", "reportlets", "executions" };
+
+ private static final String[] IGNORE_REPORT_EXECUTION_PROPERTIES = { "key", "report", "execResult" };
+
+ @Autowired
+ private ReportExecDAO reportExecDAO;
+
+ @Autowired
+ private SchedulerFactoryBean scheduler;
+
+ @Override
+ public void getReport(final Report report, final ReportTO reportTO) {
+ BeanUtils.copyProperties(reportTO, report, IGNORE_REPORT_PROPERTIES);
+
+ // 1. remove all reportlet confs
+ Set<ReportletConf> toRemove = new HashSet<>();
+ for (ReportletConf conf : report.getReportletConfs()) {
+ toRemove.add(conf);
+ }
+ for (ReportletConf conf : toRemove) {
+ report.removeReportletConf(conf);
+ }
+
+ // 2. take all reportlet confs from reportTO
+ for (ReportletConf conf : reportTO.getReportletConfs()) {
+ report.addReportletConf(conf);
+ }
+ }
+
+ @Override
+ public ReportTO getReportTO(final Report report) {
+ ReportTO reportTO = new ReportTO();
+ reportTO.setKey(report.getKey());
+ BeanUtils.copyProperties(report, reportTO, IGNORE_REPORT_PROPERTIES);
+
+ copyReportletConfs(report, reportTO);
+
+ ReportExec latestExec = reportExecDAO.findLatestStarted(report);
+ reportTO.setLatestExecStatus(latestExec == null
+ ? ""
+ : latestExec.getStatus());
+
+ reportTO.setStartDate(latestExec == null
+ ? null
+ : latestExec.getStartDate());
+
+ reportTO.setEndDate(latestExec == null
+ ? null
+ : latestExec.getEndDate());
+
+ for (ReportExec reportExec : report.getExecs()) {
+ reportTO.getExecutions().add(getReportExecTO(reportExec));
+ }
+
+ String triggerName = JobNamer.getTriggerName(JobNamer.getJobName(report));
+
+ Trigger trigger;
+ try {
+ trigger = scheduler.getScheduler().getTrigger(new TriggerKey(triggerName, Scheduler.DEFAULT_GROUP));
+ } catch (SchedulerException e) {
+ LOG.warn("While trying to get to " + triggerName, e);
+ trigger = null;
+ }
+
+ if (trigger != null) {
+ reportTO.setLastExec(trigger.getPreviousFireTime());
+ reportTO.setNextExec(trigger.getNextFireTime());
+ }
+
+ return reportTO;
+ }
+
+ private void copyReportletConfs(final Report report, final ReportTO reportTO) {
+ reportTO.getReportletConfs().clear();
+ for (ReportletConf reportletConf : report.getReportletConfs()) {
+ reportTO.getReportletConfs().add((AbstractReportletConf) reportletConf);
+ }
+ }
+
+ @Override
+ public ReportExecTO getReportExecTO(final ReportExec execution) {
+ ReportExecTO executionTO = new ReportExecTO();
+ executionTO.setKey(execution.getKey());
+ BeanUtils.copyProperties(execution, executionTO, IGNORE_REPORT_EXECUTION_PROPERTIES);
+ if (execution.getKey() != null) {
+ executionTO.setKey(execution.getKey());
+ }
+ executionTO.setReport(execution.getReport().getKey());
+
+ return executionTO;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java b/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
new file mode 100644
index 0000000..2bf756f
--- /dev/null
+++ b/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
@@ -0,0 +1,362 @@
+/*
+ * 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.provisioning.java.data;
+
+import org.apache.syncope.core.provisioning.api.data.ResourceDataBinder;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.commons.lang3.SerializationUtils;
+import org.apache.syncope.common.lib.SyncopeClientCompositeException;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.MappingItemTO;
+import org.apache.syncope.common.lib.to.MappingTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.core.persistence.api.dao.ConnInstanceDAO;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
+import org.apache.syncope.core.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.core.persistence.api.entity.ConnInstance;
+import org.apache.syncope.core.persistence.api.entity.EntityFactory;
+import org.apache.syncope.core.persistence.api.entity.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.Mapping;
+import org.apache.syncope.core.persistence.api.entity.MappingItem;
+import org.apache.syncope.core.persistence.api.entity.PasswordPolicy;
+import org.apache.syncope.core.persistence.api.entity.SyncPolicy;
+import org.apache.syncope.core.persistence.api.entity.role.RMapping;
+import org.apache.syncope.core.persistence.api.entity.role.RMappingItem;
+import org.apache.syncope.core.persistence.api.entity.user.UMapping;
+import org.apache.syncope.core.persistence.api.entity.user.UMappingItem;
+import org.apache.syncope.core.provisioning.api.ConnectorRegistry;
+import org.apache.syncope.core.misc.jexl.JexlUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.syncope.core.misc.spring.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ResourceDataBinderImpl implements ResourceDataBinder {
+
+ /**
+ * Logger.
+ */
+ private static final Logger LOG = LoggerFactory.getLogger(ResourceDataBinder.class);
+
+ private static final String[] MAPPINGITEM_IGNORE_PROPERTIES = { "key", "mapping" };
+
+ @Autowired
+ private ConnectorRegistry connRegistry;
+
+ @Autowired
+ private ConnInstanceDAO connInstanceDAO;
+
+ @Autowired
+ private PolicyDAO policyDAO;
+
+ @Autowired
+ private EntityFactory entityFactory;
+
+ @Override
+ public ExternalResource create(final ResourceTO resourceTO) {
+ return update(entityFactory.newEntity(ExternalResource.class), resourceTO);
+ }
+
+ @Override
+ public ExternalResource update(final ExternalResource resource, final ResourceTO resourceTO) {
+ if (resourceTO == null) {
+ return null;
+ }
+
+ resource.setKey(resourceTO.getKey());
+
+ if (resourceTO.getConnectorId() != null) {
+ ConnInstance connector = connInstanceDAO.find(resourceTO.getConnectorId());
+ resource.setConnector(connector);
+
+ if (!connector.getResources().contains(resource)) {
+ connector.addResource(resource);
+ }
+ }
+
+ resource.setEnforceMandatoryCondition(resourceTO.isEnforceMandatoryCondition());
+
+ resource.setPropagationPrimary(resourceTO.isPropagationPrimary());
+
+ resource.setPropagationPriority(resourceTO.getPropagationPriority());
+
+ resource.setRandomPwdIfNotProvided(resourceTO.isRandomPwdIfNotProvided());
+
+ resource.setPropagationMode(resourceTO.getPropagationMode());
+
+ if (resourceTO.getUmapping() == null || resourceTO.getUmapping().getItems().isEmpty()) {
+ resource.setUmapping(null);
+ } else {
+ UMapping mapping = entityFactory.newEntity(UMapping.class);
+ mapping.setResource(resource);
+ resource.setUmapping(mapping);
+ populateMapping(resourceTO.getUmapping(), mapping, entityFactory.newEntity(UMappingItem.class));
+ }
+ if (resourceTO.getRmapping() == null || resourceTO.getRmapping().getItems().isEmpty()) {
+ resource.setRmapping(null);
+ } else {
+ RMapping mapping = entityFactory.newEntity(RMapping.class);
+ mapping.setResource(resource);
+ resource.setRmapping(mapping);
+ populateMapping(resourceTO.getRmapping(), mapping, entityFactory.newEntity(RMappingItem.class));
+ }
+
+ resource.setCreateTraceLevel(resourceTO.getCreateTraceLevel());
+ resource.setUpdateTraceLevel(resourceTO.getUpdateTraceLevel());
+ resource.setDeleteTraceLevel(resourceTO.getDeleteTraceLevel());
+ resource.setSyncTraceLevel(resourceTO.getSyncTraceLevel());
+
+ resource.setPasswordPolicy(resourceTO.getPasswordPolicy() == null
+ ? null : (PasswordPolicy) policyDAO.find(resourceTO.getPasswordPolicy()));
+
+ resource.setAccountPolicy(resourceTO.getAccountPolicy() == null
+ ? null : (AccountPolicy) policyDAO.find(resourceTO.getAccountPolicy()));
+
+ resource.setSyncPolicy(resourceTO.getSyncPolicy() == null
+ ? null : (SyncPolicy) policyDAO.find(resourceTO.getSyncPolicy()));
+
+ resource.setConnInstanceConfiguration(new HashSet<>(resourceTO.getConnConfProperties()));
+
+ if (resourceTO.getUsyncToken() == null) {
+ resource.setUsyncToken(null);
+ }
+ if (resourceTO.getRsyncToken() == null) {
+ resource.setRsyncToken(null);
+ }
+
+ resource.getPropagationActionsClassNames().clear();
+ resource.getPropagationActionsClassNames().addAll(resourceTO.getPropagationActionsClassNames());
+
+ return resource;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private void populateMapping(final MappingTO mappingTO, final Mapping mapping, final MappingItem prototype) {
+ mapping.setAccountLink(mappingTO.getAccountLink());
+
+ for (MappingItem item : getMappingItems(mappingTO.getItems(), prototype)) {
+ item.setMapping(mapping);
+ if (item.isAccountid()) {
+ mapping.setAccountIdItem(item);
+ } else if (item.isPassword()) {
+ ((UMapping) mapping).setPasswordItem((UMappingItem) item);
+ } else {
+ mapping.addItem(item);
+ }
+ }
+ }
+
+ private Set<MappingItem> getMappingItems(final Collection<MappingItemTO> itemTOs, final MappingItem prototype) {
+ Set<MappingItem> items = new HashSet<>(itemTOs.size());
+ for (MappingItemTO itemTO : itemTOs) {
+ items.add(getMappingItem(itemTO, prototype));
+ }
+
+ return items;
+ }
+
+ private MappingItem getMappingItem(final MappingItemTO itemTO, final MappingItem prototype) {
+ if (itemTO == null || itemTO.getIntMappingType() == null) {
+ LOG.error("Null mappingTO provided");
+ return null;
+ }
+
+ SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
+
+ SyncopeClientException requiredValuesMissing = SyncopeClientException.build(
+ ClientExceptionType.RequiredValuesMissing);
+
+ if (itemTO.getIntAttrName() == null) {
+ if (IntMappingType.getEmbedded().contains(itemTO.getIntMappingType())) {
+ itemTO.setIntAttrName(itemTO.getIntMappingType().toString());
+ } else {
+ requiredValuesMissing.getElements().add("intAttrName");
+ }
+ }
+
+ // Throw composite exception if there is at least one element set
+ // in the composing exceptions
+ if (!requiredValuesMissing.isEmpty()) {
+ scce.addException(requiredValuesMissing);
+ }
+
+ // no mandatory condition implies mandatory condition false
+ if (!JexlUtil.isExpressionValid(itemTO.getMandatoryCondition() == null
+ ? "false" : itemTO.getMandatoryCondition())) {
+
+ SyncopeClientException invalidMandatoryCondition = SyncopeClientException.build(
+ ClientExceptionType.InvalidValues);
+
+ invalidMandatoryCondition.getElements().add(itemTO.getMandatoryCondition());
+
+ scce.addException(invalidMandatoryCondition);
+ }
+
+ if (scce.hasExceptions()) {
+ throw scce;
+ }
+
+ MappingItem item = SerializationUtils.clone(prototype);
+ BeanUtils.copyProperties(itemTO, item, MAPPINGITEM_IGNORE_PROPERTIES);
+ return item;
+ }
+
+ @Override
+ public ConnInstance getConnInstance(final ResourceTO resourceTO) {
+ ConnInstance connInstance = connInstanceDAO.find(resourceTO.getConnectorId());
+ if (connInstance == null) {
+ throw new NotFoundException("Connector '" + resourceTO.getConnectorId() + "'");
+ }
+
+ final ConnInstance connInstanceClone = SerializationUtils.clone(connInstance);
+ return connRegistry.getOverriddenConnInstance(connInstanceClone, resourceTO.getConnConfProperties());
+ }
+
+ @Override
+ public List<ResourceTO> getResourceTOs(final Collection<? extends ExternalResource> resources) {
+ List<ResourceTO> resourceTOs = new ArrayList<>();
+ for (ExternalResource resource : resources) {
+ resourceTOs.add(getResourceTO(resource));
+ }
+
+ return resourceTOs;
+ }
+
+ @Override
+ public ResourceTO getResourceTO(final ExternalResource resource) {
+ if (resource == null) {
+ return null;
+ }
+
+ ResourceTO resourceTO = new ResourceTO();
+
+ // set sys info
+ resourceTO.setCreator(resource.getCreator());
+ resourceTO.setCreationDate(resource.getCreationDate());
+ resourceTO.setLastModifier(resource.getLastModifier());
+ resourceTO.setLastChangeDate(resource.getLastChangeDate());
+
+ // set the resource name
+ resourceTO.setKey(resource.getKey());
+
+ // set the connector instance
+ ConnInstance connector = resource.getConnector();
+
+ resourceTO.setConnectorId(connector == null ? null : connector.getKey());
+ resourceTO.setConnectorDisplayName(connector == null ? null : connector.getDisplayName());
+
+ // set the mappings
+ if (resource.getUmapping() != null) {
+ MappingTO mappingTO = new MappingTO();
+ resourceTO.setUmapping(mappingTO);
+ populateMappingTO(resource.getUmapping(), mappingTO);
+ }
+ if (resource.getRmapping() != null) {
+ MappingTO mappingTO = new MappingTO();
+ resourceTO.setRmapping(mappingTO);
+ populateMappingTO(resource.getRmapping(), mappingTO);
+ }
+
+ resourceTO.setEnforceMandatoryCondition(resource.isEnforceMandatoryCondition());
+
+ resourceTO.setPropagationPrimary(resource.isPropagationPrimary());
+
+ resourceTO.setPropagationPriority(resource.getPropagationPriority());
+
+ resourceTO.setRandomPwdIfNotProvided(resource.isRandomPwdIfNotProvided());
+
+ resourceTO.setPropagationMode(resource.getPropagationMode());
+
+ resourceTO.setCreateTraceLevel(resource.getCreateTraceLevel());
+ resourceTO.setUpdateTraceLevel(resource.getUpdateTraceLevel());
+ resourceTO.setDeleteTraceLevel(resource.getDeleteTraceLevel());
+ resourceTO.setSyncTraceLevel(resource.getSyncTraceLevel());
+
+ resourceTO.setPasswordPolicy(resource.getPasswordPolicy() == null
+ ? null : resource.getPasswordPolicy().getKey());
+
+ resourceTO.setAccountPolicy(resource.getAccountPolicy() == null
+ ? null : resource.getAccountPolicy().getKey());
+
+ resourceTO.setSyncPolicy(resource.getSyncPolicy() == null
+ ? null : resource.getSyncPolicy().getKey());
+
+ resourceTO.getConnConfProperties().addAll(resource.getConnInstanceConfiguration());
+
+ resourceTO.setUsyncToken(resource.getSerializedUSyncToken());
+ resourceTO.setRsyncToken(resource.getSerializedRSyncToken());
+
+ resourceTO.getPropagationActionsClassNames().addAll(resource.getPropagationActionsClassNames());
+
+ return resourceTO;
+ }
+
+ private void populateMappingTO(final Mapping<?> mapping, final MappingTO mappingTO) {
+ mappingTO.setAccountLink(mapping.getAccountLink());
+
+ for (MappingItemTO itemTO : getMappingItemTOs(mapping.getItems())) {
+ if (itemTO.isAccountid()) {
+ mappingTO.setAccountIdItem(itemTO);
+ } else if (itemTO.isPassword()) {
+ mappingTO.setPasswordItem(itemTO);
+ } else {
+ mappingTO.addItem(itemTO);
+ }
+ }
+ }
+
+ private Set<MappingItemTO> getMappingItemTOs(final Collection<? extends MappingItem> items) {
+ Set<MappingItemTO> mappingTOs = new HashSet<>();
+ for (MappingItem item : items) {
+ LOG.debug("Asking for TO for {}", item);
+ mappingTOs.add(getMappingItemTO(item));
+ }
+
+ LOG.debug("Collected TOs: {}", mappingTOs);
+
+ return mappingTOs;
+ }
+
+ private MappingItemTO getMappingItemTO(final MappingItem item) {
+ if (item == null) {
+ LOG.error("Provided null mapping");
+
+ return null;
+ }
+
+ MappingItemTO itemTO = new MappingItemTO();
+
+ BeanUtils.copyProperties(item, itemTO, MAPPINGITEM_IGNORE_PROPERTIES);
+
+ itemTO.setKey(item.getKey());
+
+ LOG.debug("Obtained SchemaMappingTO {}", itemTO);
+
+ return itemTO;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java b/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java
new file mode 100644
index 0000000..2e12820
--- /dev/null
+++ b/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java
@@ -0,0 +1,411 @@
+/*
+ * 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.provisioning.java.data;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.apache.syncope.common.lib.SyncopeClientCompositeException;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.mod.RoleMod;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.core.persistence.api.dao.EntitlementDAO;
+import org.apache.syncope.core.persistence.api.entity.AccountPolicy;
+import org.apache.syncope.core.persistence.api.entity.AttrTemplate;
+import org.apache.syncope.core.persistence.api.entity.Entitlement;
+import org.apache.syncope.core.persistence.api.entity.PasswordPolicy;
+import org.apache.syncope.core.persistence.api.entity.Schema;
+import org.apache.syncope.core.persistence.api.entity.membership.MDerAttrTemplate;
+import org.apache.syncope.core.persistence.api.entity.membership.MDerSchema;
+import org.apache.syncope.core.persistence.api.entity.membership.MPlainAttrTemplate;
+import org.apache.syncope.core.persistence.api.entity.membership.MPlainSchema;
+import org.apache.syncope.core.persistence.api.entity.membership.MVirAttrTemplate;
+import org.apache.syncope.core.persistence.api.entity.membership.MVirSchema;
+import org.apache.syncope.core.persistence.api.entity.role.RDerAttr;
+import org.apache.syncope.core.persistence.api.entity.role.RDerAttrTemplate;
+import org.apache.syncope.core.persistence.api.entity.role.RDerSchema;
+import org.apache.syncope.core.persistence.api.entity.role.RPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.role.RPlainAttrTemplate;
+import org.apache.syncope.core.persistence.api.entity.role.RPlainSchema;
+import org.apache.syncope.core.persistence.api.entity.role.RVirAttr;
+import org.apache.syncope.core.persistence.api.entity.role.RVirAttrTemplate;
+import org.apache.syncope.core.persistence.api.entity.role.RVirSchema;
+import org.apache.syncope.core.persistence.api.entity.role.Role;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.common.lib.types.PropagationByResource;
+import org.apache.syncope.core.provisioning.api.data.RoleDataBinder;
+import org.apache.syncope.core.misc.ConnObjectUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+@Component
+@Transactional(rollbackFor = { Throwable.class })
+public class RoleDataBinderImpl extends AbstractAttributableDataBinder implements RoleDataBinder {
+
+ @Autowired
+ private ConnObjectUtil connObjectUtil;
+
+ @Autowired
+ private EntitlementDAO entitlementDAO;
+
+ private <T extends AttrTemplate<S>, S extends Schema> void setAttrTemplates(
+ final Role role, final List<String> schemaNames,
+ final Class<T> templateClass, final Class<S> schemaClass) {
+
+ List<T> toRemove = new ArrayList<>();
+ for (T template : role.getAttrTemplates(templateClass)) {
+ if (!schemaNames.contains(template.getSchema().getKey())) {
+ toRemove.add(template);
+ }
+ }
+ role.getAttrTemplates(templateClass).removeAll(toRemove);
+
+ for (String schemaName : schemaNames) {
+ if (role.getAttrTemplate(templateClass, schemaName) == null) {
+ S schema = getSchema(schemaName, schemaClass);
+ if (schema != null) {
+ try {
+ T template = entityFactory.newEntity(templateClass);
+ template.setSchema(schema);
+ template.setOwner(role);
+ role.getAttrTemplates(templateClass).add(template);
+ } catch (Exception e) {
+ LOG.error("Could not create template for {}", templateClass, e);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public Role create(final Role role, final RoleTO roleTO) {
+ role.setInheritOwner(roleTO.isInheritOwner());
+
+ role.setInheritPlainAttrs(roleTO.isInheritPlainAttrs());
+ role.setInheritDerAttrs(roleTO.isInheritDerAttrs());
+ role.setInheritVirAttrs(roleTO.isInheritVirAttrs());
+
+ role.setInheritTemplates(roleTO.isInheritTemplates());
+
+ role.setInheritPasswordPolicy(roleTO.isInheritPasswordPolicy());
+ role.setInheritAccountPolicy(roleTO.isInheritAccountPolicy());
+
+ SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
+
+ // name and parent
+ SyncopeClientException invalidRoles = SyncopeClientException.build(ClientExceptionType.InvalidRoles);
+ if (roleTO.getName() == null) {
+ LOG.error("No name specified for this role");
+
+ invalidRoles.getElements().add("No name specified for this role");
+ } else {
+ role.setName(roleTO.getName());
+ }
+ Long parentRoleKey = null;
+ if (roleTO.getParent() != 0) {
+ Role parentRole = roleDAO.find(roleTO.getParent());
+ if (parentRole == null) {
+ LOG.error("Could not find role with id " + roleTO.getParent());
+
+ invalidRoles.getElements().add(String.valueOf(roleTO.getParent()));
+ scce.addException(invalidRoles);
+ } else {
+ role.setParent(parentRole);
+ parentRoleKey = role.getParent().getKey();
+ }
+ }
+
+ Role otherRole = roleDAO.find(roleTO.getName(), parentRoleKey);
+ if (otherRole != null) {
+ LOG.error("Another role exists with the same name " + "and the same parent role: " + otherRole);
+
+ invalidRoles.getElements().add(roleTO.getName());
+ }
+
+ // attribute templates
+ setAttrTemplates(role, roleTO.getRPlainAttrTemplates(), RPlainAttrTemplate.class, RPlainSchema.class);
+ setAttrTemplates(role, roleTO.getRDerAttrTemplates(), RDerAttrTemplate.class, RDerSchema.class);
+ setAttrTemplates(role, roleTO.getRVirAttrTemplates(), RVirAttrTemplate.class, RVirSchema.class);
+ setAttrTemplates(role, roleTO.getMPlainAttrTemplates(), MPlainAttrTemplate.class, MPlainSchema.class);
+ setAttrTemplates(role, roleTO.getMDerAttrTemplates(), MDerAttrTemplate.class, MDerSchema.class);
+ setAttrTemplates(role, roleTO.getMVirAttrTemplates(), MVirAttrTemplate.class, MVirSchema.class);
+
+ // attributes, derived attributes, virtual attributes and resources
+ fill(role, roleTO, attrUtilFactory.getInstance(AttributableType.ROLE), scce);
+
+ // entitlements
+ for (String entitlementName : roleTO.getEntitlements()) {
+ Entitlement entitlement = entitlementDAO.find(entitlementName);
+ if (entitlement == null) {
+ LOG.warn("Ignoring invalid entitlement {}", entitlementName);
+ } else {
+ role.addEntitlement(entitlement);
+ }
+ }
+
+ // owner
+ if (roleTO.getUserOwner() != null) {
+ User owner = userDAO.find(roleTO.getUserOwner());
+ if (owner == null) {
+ LOG.warn("Ignoring invalid user specified as owner: {}", roleTO.getUserOwner());
+ } else {
+ role.setUserOwner(owner);
+ }
+ }
+ if (roleTO.getRoleOwner() != null) {
+ Role owner = roleDAO.find(roleTO.getRoleOwner());
+ if (owner == null) {
+ LOG.warn("Ignoring invalid role specified as owner: {}", roleTO.getRoleOwner());
+ } else {
+ role.setRoleOwner(owner);
+ }
+ }
+
+ // policies
+ if (roleTO.getPasswordPolicy() != null) {
+ role.setPasswordPolicy((PasswordPolicy) policyDAO.find(roleTO.getPasswordPolicy()));
+ }
+ if (roleTO.getAccountPolicy() != null) {
+ role.setAccountPolicy((AccountPolicy) policyDAO.find(roleTO.getAccountPolicy()));
+ }
+
+ return role;
+ }
+
+ @Override
+ public PropagationByResource update(final Role role, final RoleMod roleMod) {
+ PropagationByResource propByRes = new PropagationByResource();
+
+ SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
+
+ // fetch account ids before update
+ Map<String, String> oldAccountIds = getAccountIds(role, AttributableType.ROLE);
+
+ // name
+ SyncopeClientException invalidRoles = SyncopeClientException.build(ClientExceptionType.InvalidRoles);
+ if (roleMod.getName() != null) {
+ Role otherRole = roleDAO.find(roleMod.getName(),
+ role.getParent() == null ? null : role.getParent().getKey());
+ if (otherRole == null || role.equals(otherRole)) {
+ if (!roleMod.getName().equals(role.getName())) {
+ propByRes.addAll(ResourceOperation.UPDATE, role.getResourceNames());
+
+ role.setName(roleMod.getName());
+ }
+ } else {
+ LOG.error("Another role exists with the same name and the same parent role: " + otherRole);
+
+ invalidRoles.getElements().add(roleMod.getName());
+ scce.addException(invalidRoles);
+ }
+ }
+
+ if (roleMod.getInheritOwner() != null) {
+ role.setInheritOwner(roleMod.getInheritOwner());
+ }
+
+ if (roleMod.getInheritTemplates() != null) {
+ role.setInheritTemplates(roleMod.getInheritTemplates());
+ }
+
+ if (roleMod.getInheritPlainAttrs() != null) {
+ role.setInheritPlainAttrs(roleMod.getInheritPlainAttrs());
+ }
+ if (roleMod.getInheritDerAttrs() != null) {
+ role.setInheritDerAttrs(roleMod.getInheritDerAttrs());
+ }
+ if (roleMod.getInheritVirAttrs() != null) {
+ role.setInheritVirAttrs(roleMod.getInheritVirAttrs());
+ }
+
+ if (roleMod.getInheritPasswordPolicy() != null) {
+ role.setInheritPasswordPolicy(roleMod.getInheritPasswordPolicy());
+ }
+ if (roleMod.getInheritAccountPolicy() != null) {
+ role.setInheritAccountPolicy(roleMod.getInheritAccountPolicy());
+ }
+
+ // entitlements
+ if (roleMod.isModEntitlements()) {
+ role.getEntitlements().clear();
+ for (String entitlementName : roleMod.getEntitlements()) {
+ Entitlement entitlement = entitlementDAO.find(entitlementName);
+ if (entitlement == null) {
+ LOG.warn("Ignoring invalid entitlement {}", entitlementName);
+ } else {
+ role.addEntitlement(entitlement);
+ }
+ }
+ }
+
+ // attribute templates
+ if (roleMod.isModRAttrTemplates()) {
+ setAttrTemplates(role, roleMod.getRPlainAttrTemplates(), RPlainAttrTemplate.class, RPlainSchema.class);
+ }
+ if (roleMod.isModRDerAttrTemplates()) {
+ setAttrTemplates(role, roleMod.getRDerAttrTemplates(), RDerAttrTemplate.class, RDerSchema.class);
+ }
+ if (roleMod.isModRVirAttrTemplates()) {
+ setAttrTemplates(role, roleMod.getRVirAttrTemplates(), RVirAttrTemplate.class, RVirSchema.class);
+ }
+ if (roleMod.isModMAttrTemplates()) {
+ setAttrTemplates(role, roleMod.getMPlainAttrTemplates(), MPlainAttrTemplate.class, MPlainSchema.class);
+ }
+ if (roleMod.isModMDerAttrTemplates()) {
+ setAttrTemplates(role, roleMod.getMDerAttrTemplates(), MDerAttrTemplate.class, MDerSchema.class);
+ }
+ if (roleMod.isModMVirAttrTemplates()) {
+ setAttrTemplates(role, roleMod.getMVirAttrTemplates(), MVirAttrTemplate.class, MVirSchema.class);
+ }
+
+ // policies
+ if (roleMod.getPasswordPolicy() != null) {
+ role.setPasswordPolicy(roleMod.getPasswordPolicy().getKey() == null
+ ? null
+ : (PasswordPolicy) policyDAO.find(roleMod.getPasswordPolicy().getKey()));
+ }
+ if (roleMod.getAccountPolicy() != null) {
+ role.setAccountPolicy(roleMod.getAccountPolicy().getKey() == null
+ ? null
+ : (AccountPolicy) policyDAO.find(roleMod.getAccountPolicy().getKey()));
+ }
+
+ // owner
+ if (roleMod.getUserOwner() != null) {
+ role.setUserOwner(roleMod.getUserOwner().getKey() == null
+ ? null
+ : userDAO.find(roleMod.getUserOwner().getKey()));
+ }
+ if (roleMod.getRoleOwner() != null) {
+ role.setRoleOwner(roleMod.getRoleOwner().getKey() == null
+ ? null
+ : roleDAO.find(roleMod.getRoleOwner().getKey()));
+ }
+
+ // attributes, derived attributes, virtual attributes and resources
+ propByRes.merge(fill(role, roleMod, attrUtilFactory.getInstance(AttributableType.ROLE), scce));
+
+ // check if some account id was changed by the update above
+ Map<String, String> newAccountIds = getAccountIds(role, AttributableType.ROLE);
+ for (Map.Entry<String, String> entry : oldAccountIds.entrySet()) {
+ if (newAccountIds.containsKey(entry.getKey())
+ && !entry.getValue().equals(newAccountIds.get(entry.getKey()))) {
+
+ propByRes.addOldAccountId(entry.getKey(), entry.getValue());
+ propByRes.add(ResourceOperation.UPDATE, entry.getKey());
+ }
+ }
+
+ return propByRes;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Transactional(readOnly = true)
+ @Override
+ public RoleTO getRoleTO(final Role role) {
+ connObjectUtil.retrieveVirAttrValues(role, attrUtilFactory.getInstance(AttributableType.ROLE));
+
+ RoleTO roleTO = new RoleTO();
+
+ // set sys info
+ roleTO.setCreator(role.getCreator());
+ roleTO.setCreationDate(role.getCreationDate());
+ roleTO.setLastModifier(role.getLastModifier());
+ roleTO.setLastChangeDate(role.getLastChangeDate());
+
+ roleTO.setKey(role.getKey());
+ roleTO.setName(role.getName());
+
+ roleTO.setInheritOwner(role.isInheritOwner());
+
+ roleTO.setInheritTemplates(role.isInheritTemplates());
+
+ roleTO.setInheritPlainAttrs(role.isInheritPlainAttrs());
+ roleTO.setInheritDerAttrs(role.isInheritDerAttrs());
+ roleTO.setInheritVirAttrs(role.isInheritVirAttrs());
+
+ roleTO.setInheritPasswordPolicy(role.isInheritPasswordPolicy());
+ roleTO.setInheritAccountPolicy(role.isInheritAccountPolicy());
+
+ if (role.getParent() != null) {
+ roleTO.setParent(role.getParent().getKey());
+ }
+
+ if (role.getUserOwner() != null) {
+ roleTO.setUserOwner(role.getUserOwner().getKey());
+ }
+ if (role.getRoleOwner() != null) {
+ roleTO.setRoleOwner(role.getRoleOwner().getKey());
+ }
+
+ // -------------------------
+ // Retrieve all [derived/virtual] attributes (inherited and not)
+ // -------------------------
+ final List<? extends RPlainAttr> allAttributes = role.findLastInheritedAncestorPlainAttrs();
+
+ final List<? extends RDerAttr> allDerAttributes = role.findLastInheritedAncestorDerAttrs();
+
+ final List<? extends RVirAttr> allVirAttributes = role.findLastInheritedAncestorVirAttrs();
+ // -------------------------
+
+ fillTO(roleTO, allAttributes, allDerAttributes, allVirAttributes, role.getResources());
+
+ for (Entitlement entitlement : role.getEntitlements()) {
+ roleTO.getEntitlements().add(entitlement.getKey());
+ }
+
+ for (RPlainAttrTemplate template : role.findInheritedTemplates(RPlainAttrTemplate.class)) {
+ roleTO.getRPlainAttrTemplates().add(template.getSchema().getKey());
+ }
+ for (RDerAttrTemplate template : role.findInheritedTemplates(RDerAttrTemplate.class)) {
+ roleTO.getRDerAttrTemplates().add(template.getSchema().getKey());
+ }
+ for (RVirAttrTemplate template : role.findInheritedTemplates(RVirAttrTemplate.class)) {
+ roleTO.getRVirAttrTemplates().add(template.getSchema().getKey());
+ }
+ for (MPlainAttrTemplate template : role.findInheritedTemplates(MPlainAttrTemplate.class)) {
+ roleTO.getMPlainAttrTemplates().add(template.getSchema().getKey());
+ }
+ for (MDerAttrTemplate template : role.findInheritedTemplates(MDerAttrTemplate.class)) {
+ roleTO.getMDerAttrTemplates().add(template.getSchema().getKey());
+ }
+ for (MVirAttrTemplate template : role.findInheritedTemplates(MVirAttrTemplate.class)) {
+ roleTO.getMVirAttrTemplates().add(template.getSchema().getKey());
+ }
+
+ roleTO.setPasswordPolicy(role.getPasswordPolicy() == null
+ ? null
+ : role.getPasswordPolicy().getKey());
+ roleTO.setAccountPolicy(role.getAccountPolicy() == null
+ ? null
+ : role.getAccountPolicy().getKey());
+
+ return roleTO;
+ }
+
+ @Transactional(readOnly = true)
+ @Override
+ public RoleTO getRoleTO(final Long key) {
+ return getRoleTO(roleDAO.authFetch(key));
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java b/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
new file mode 100644
index 0000000..c0adde2
--- /dev/null
+++ b/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
@@ -0,0 +1,170 @@
+/*
+ * 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.provisioning.java.data;
+
+import org.apache.syncope.core.provisioning.api.data.SchemaDataBinder;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.SyncopeClientCompositeException;
+import org.apache.syncope.common.lib.SyncopeClientException;
+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.ClientExceptionType;
+import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.core.persistence.api.entity.AttributableUtil;
+import org.apache.syncope.core.persistence.api.entity.DerSchema;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.VirSchema;
+import org.apache.syncope.core.misc.spring.BeanUtils;
+import org.apache.syncope.core.misc.jexl.JexlUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SchemaDataBinderImpl implements SchemaDataBinder {
+
+ @Autowired
+ private PlainSchemaDAO schemaDAO;
+
+ // --------------- PLAIN -----------------
+ private <T extends PlainSchema> void fill(final T schema, final PlainSchemaTO schemaTO) {
+ if (!JexlUtil.isExpressionValid(schemaTO.getMandatoryCondition())) {
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidValues);
+ sce.getElements().add(schemaTO.getMandatoryCondition());
+ throw sce;
+ }
+
+ BeanUtils.copyProperties(schemaTO, schema);
+ }
+
+ @Override
+ public <T extends PlainSchema> void create(final PlainSchemaTO schemaTO, final T schema) {
+ fill(schema, schemaTO);
+ }
+
+ @Override
+ public <T extends PlainSchema> void update(final PlainSchemaTO schemaTO, final T schema,
+ final AttributableUtil attributableUtil) {
+
+ SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
+
+ List<PlainAttr> attrs = schemaDAO.findAttrs(schema, attributableUtil.plainAttrClass());
+ if (!attrs.isEmpty()) {
+ if (schema.getType() != schemaTO.getType()) {
+ SyncopeClientException e = SyncopeClientException.build(ClientExceptionType.InvalidPlainSchema);
+ e.getElements().add("Cannot change type since " + schema.getKey() + " has attributes");
+
+ scce.addException(e);
+ }
+ if (schema.isUniqueConstraint() != schemaTO.isUniqueConstraint()) {
+ SyncopeClientException e = SyncopeClientException.build(ClientExceptionType.InvalidPlainSchema);
+ e.getElements().add("Cannot alter unique contraint since " + schema.getKey() + " has attributes");
+
+ scce.addException(e);
+ }
+ }
+
+ if (scce.hasExceptions()) {
+ throw scce;
+ }
+
+ fill(schema, schemaTO);
+ }
+
+ @Override
+ public <T extends PlainSchema> PlainSchemaTO getSchemaTO(
+ final T schema, final AttributableUtil attributableUtil) {
+
+ PlainSchemaTO schemaTO = new PlainSchemaTO();
+ BeanUtils.copyProperties(schema, schemaTO);
+
+ return schemaTO;
+ }
+
+ // --------------- DERIVED -----------------
+ private <T extends DerSchema> T populate(final T derSchema, final DerSchemaTO derSchemaTO) {
+ SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
+
+ if (StringUtils.isBlank(derSchemaTO.getExpression())) {
+ SyncopeClientException requiredValuesMissing =
+ SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
+ requiredValuesMissing.getElements().add("expression");
+
+ scce.addException(requiredValuesMissing);
+ } else if (!JexlUtil.isExpressionValid(derSchemaTO.getExpression())) {
+ SyncopeClientException e = SyncopeClientException.build(ClientExceptionType.InvalidValues);
+ e.getElements().add(derSchemaTO.getExpression());
+
+ scce.addException(e);
+ }
+
+ if (scce.hasExceptions()) {
+ throw scce;
+ }
+
+ BeanUtils.copyProperties(derSchemaTO, derSchema);
+
+ return derSchema;
+ }
+
+ @Override
+ public <T extends DerSchema> T create(final DerSchemaTO derSchemaTO, final T derSchema) {
+ return populate(derSchema, derSchemaTO);
+ }
+
+ @Override
+ public <T extends DerSchema> T update(final DerSchemaTO derSchemaTO, final T derSchema) {
+ return populate(derSchema, derSchemaTO);
+ }
+
+ @Override
+ public <T extends DerSchema> DerSchemaTO getDerSchemaTO(final T derSchema) {
+ DerSchemaTO derSchemaTO = new DerSchemaTO();
+ BeanUtils.copyProperties(derSchema, derSchemaTO);
+
+ return derSchemaTO;
+ }
+
+ // --------------- VIRTUAL -----------------
+ private <T extends VirSchema> T fill(final T virSchema, final VirSchemaTO virSchemaTO) {
+ BeanUtils.copyProperties(virSchemaTO, virSchema);
+
+ return virSchema;
+ }
+
+ @Override
+ public <T extends VirSchema> T create(final VirSchemaTO virSchemaTO, final T virSchema) {
+ return fill(virSchema, virSchemaTO);
+ }
+
+ @Override
+ public <T extends VirSchema> T update(final VirSchemaTO virSchemaTO, final T virSchema) {
+ return fill(virSchema, virSchemaTO);
+ }
+
+ @Override
+ public <T extends VirSchema> VirSchemaTO getVirSchemaTO(final T virSchema) {
+ VirSchemaTO virSchemaTO = new VirSchemaTO();
+ BeanUtils.copyProperties(virSchema, virSchemaTO);
+
+ return virSchemaTO;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SecurityQuestionDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SecurityQuestionDataBinderImpl.java b/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SecurityQuestionDataBinderImpl.java
new file mode 100644
index 0000000..34523f2
--- /dev/null
+++ b/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SecurityQuestionDataBinderImpl.java
@@ -0,0 +1,55 @@
+/*
+ * 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.provisioning.java.data;
+
+import org.apache.syncope.core.provisioning.api.data.SecurityQuestionDataBinder;
+import org.apache.syncope.common.lib.to.SecurityQuestionTO;
+import org.apache.syncope.core.persistence.api.entity.EntityFactory;
+import org.apache.syncope.core.persistence.api.entity.user.SecurityQuestion;
+import org.apache.syncope.core.misc.spring.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SecurityQuestionDataBinderImpl implements SecurityQuestionDataBinder {
+
+ @Autowired
+ private EntityFactory entityFactory;
+
+ @Override
+ public SecurityQuestionTO getSecurityQuestionTO(final SecurityQuestion securityQuestion) {
+ SecurityQuestionTO securityQuestionTO = new SecurityQuestionTO();
+
+ BeanUtils.copyProperties(securityQuestion, securityQuestionTO);
+
+ return securityQuestionTO;
+ }
+
+ @Override
+ public SecurityQuestion create(final SecurityQuestionTO securityQuestionTO) {
+ SecurityQuestion result = entityFactory.newEntity(SecurityQuestion.class);
+ update(result, securityQuestionTO);
+ return result;
+ }
+
+ @Override
+ public void update(final SecurityQuestion securityQuestion, final SecurityQuestionTO securityQuestionTO) {
+ BeanUtils.copyProperties(securityQuestionTO, securityQuestion, "key");
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java b/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
new file mode 100644
index 0000000..091c108
--- /dev/null
+++ b/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
@@ -0,0 +1,343 @@
+/*
+ * 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.provisioning.java.data;
+
+import org.apache.syncope.core.provisioning.api.data.TaskDataBinder;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.syncope.common.lib.to.AbstractProvisioningTaskTO;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.PropagationTaskTO;
+import org.apache.syncope.common.lib.to.PushTaskTO;
+import org.apache.syncope.common.lib.to.RoleTO;
+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.to.UserTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.MatchingRule;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.common.lib.types.UnmatchingRule;
+import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.TaskExecDAO;
+import org.apache.syncope.core.persistence.api.entity.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.task.NotificationTask;
+import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.core.persistence.api.entity.task.ProvisioningTask;
+import org.apache.syncope.core.persistence.api.entity.task.PushTask;
+import org.apache.syncope.core.persistence.api.entity.task.SchedTask;
+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.persistence.api.entity.task.TaskExec;
+import org.apache.syncope.core.persistence.api.entity.task.TaskUtil;
+import org.apache.syncope.core.provisioning.api.job.JobNamer;
+import org.apache.syncope.core.misc.spring.BeanUtils;
+import org.apache.syncope.core.misc.jexl.JexlUtil;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.Trigger;
+import org.quartz.TriggerKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.quartz.SchedulerFactoryBean;
+import org.springframework.stereotype.Component;
+
+@Component
+public class TaskDataBinderImpl implements TaskDataBinder {
+
+ /**
+ * Logger.
+ */
+ private static final Logger LOG = LoggerFactory.getLogger(TaskDataBinder.class);
+
+ private static final String[] IGNORE_TASK_PROPERTIES = {
+ "executions", "resource", "matchingRule", "unmatchingRule" };
+
+ private static final String[] IGNORE_TASK_EXECUTION_PROPERTIES = { "key", "task" };
+
+ @Autowired
+ private ExternalResourceDAO resourceDAO;
+
+ @Autowired
+ private TaskExecDAO taskExecDAO;
+
+ @Autowired
+ private SchedulerFactoryBean scheduler;
+
+ private void checkJexl(final AbstractAttributableTO attributableTO, final SyncopeClientException sce) {
+ for (AttrTO attrTO : attributableTO.getPlainAttrs()) {
+ if (!attrTO.getValues().isEmpty() && !JexlUtil.isExpressionValid(attrTO.getValues().get(0))) {
+ sce.getElements().add("Invalid JEXL: " + attrTO.getValues().get(0));
+ }
+ }
+
+ for (AttrTO attrTO : attributableTO.getVirAttrs()) {
+ if (!attrTO.getValues().isEmpty() && !JexlUtil.isExpressionValid(attrTO.getValues().get(0))) {
+ sce.getElements().add("Invalid JEXL: " + attrTO.getValues().get(0));
+ }
+ }
+ }
+
+ private void fill(final ProvisioningTask task, final AbstractProvisioningTaskTO taskTO) {
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidSyncTask);
+
+ if (task instanceof PushTask && taskTO instanceof PushTaskTO) {
+ final PushTask pushTask = (PushTask) task;
+ final PushTaskTO pushTaskTO = (PushTaskTO) taskTO;
+
+ pushTask.setUserFilter(pushTaskTO.getUserFilter());
+ pushTask.setRoleFilter(pushTaskTO.getRoleFilter());
+
+ pushTask.setMatchingRule(pushTaskTO.getMatchingRule() == null
+ ? MatchingRule.LINK : pushTaskTO.getMatchingRule());
+
+ pushTask.setUnmatchingRule(pushTaskTO.getUnmatchingRule() == null
+ ? UnmatchingRule.ASSIGN : pushTaskTO.getUnmatchingRule());
+
+ } else if (task instanceof SyncTask && taskTO instanceof SyncTaskTO) {
+ final SyncTask syncTask = (SyncTask) task;
+ final SyncTaskTO syncTaskTO = (SyncTaskTO) taskTO;
+
+ syncTask.setMatchingRule(syncTaskTO.getMatchingRule() == null
+ ? MatchingRule.UPDATE : syncTaskTO.getMatchingRule());
+
+ syncTask.setUnmatchingRule(syncTaskTO.getUnmatchingRule() == null
+ ? UnmatchingRule.PROVISION : syncTaskTO.getUnmatchingRule());
+
+ // 1. validate JEXL expressions in user and role templates
+ if (syncTaskTO.getUserTemplate() != null) {
+ UserTO template = syncTaskTO.getUserTemplate();
+
+ if (StringUtils.isNotBlank(template.getUsername())
+ && !JexlUtil.isExpressionValid(template.getUsername())) {
+
+ sce.getElements().add("Invalid JEXL: " + template.getUsername());
+ }
+ if (StringUtils.isNotBlank(template.getPassword())
+ && !JexlUtil.isExpressionValid(template.getPassword())) {
+
+ sce.getElements().add("Invalid JEXL: " + template.getPassword());
+ }
+
+ checkJexl(template, sce);
+
+ for (MembershipTO memb : template.getMemberships()) {
+ checkJexl(memb, sce);
+ }
+ }
+ if (syncTaskTO.getRoleTemplate() != null) {
+ RoleTO template = syncTaskTO.getRoleTemplate();
+
+ if (StringUtils.isNotBlank(template.getName()) && !JexlUtil.isExpressionValid(template.getName())) {
+ sce.getElements().add("Invalid JEXL: " + template.getName());
+ }
+
+ checkJexl(template, sce);
+ }
+ if (!sce.isEmpty()) {
+ throw sce;
+ }
+
+ // 2. all JEXL expressions are valid: accept user and role templates
+ syncTask.setUserTemplate(syncTaskTO.getUserTemplate());
+ syncTask.setRoleTemplate(syncTaskTO.getRoleTemplate());
+
+ syncTask.setFullReconciliation(syncTaskTO.isFullReconciliation());
+ }
+
+ // 3. fill the remaining fields
+ task.setPerformCreate(taskTO.isPerformCreate());
+ task.setPerformUpdate(taskTO.isPerformUpdate());
+ task.setPerformDelete(taskTO.isPerformDelete());
+ task.setSyncStatus(taskTO.isSyncStatus());
+ task.getActionsClassNames().clear();
+ task.getActionsClassNames().addAll(taskTO.getActionsClassNames());
+ }
+
+ @Override
+ public SchedTask createSchedTask(final SchedTaskTO taskTO, final TaskUtil taskUtil) {
+ final Class<? extends AbstractTaskTO> taskTOClass = taskUtil.taskTOClass();
+
+ if (taskTOClass == null || !taskTOClass.equals(taskTO.getClass())) {
+ throw new IllegalArgumentException(
+ String.format("taskUtil is type %s but task is not: %s", taskTOClass, taskTO.getClass()));
+ }
+
+ SchedTask task = taskUtil.newTask();
+ task.setCronExpression(taskTO.getCronExpression());
+ task.setName(taskTO.getName());
+ task.setDescription(taskTO.getDescription());
+
+ if (taskUtil.getType() == TaskType.SCHEDULED) {
+ task.setJobClassName(taskTO.getJobClassName());
+ } else if (taskTO instanceof AbstractProvisioningTaskTO) {
+ final AbstractProvisioningTaskTO provisioningTaskTO = (AbstractProvisioningTaskTO) taskTO;
+
+ ExternalResource resource = resourceDAO.find(provisioningTaskTO.getResource());
+ if (resource == null) {
+ throw new NotFoundException("Resource " + provisioningTaskTO.getResource());
+ }
+ ((ProvisioningTask) task).setResource(resource);
+
+ fill((ProvisioningTask) task, provisioningTaskTO);
+ }
+
+ return task;
+ }
+
+ @Override
+ public void updateSchedTask(final SchedTask task, final SchedTaskTO taskTO, final TaskUtil taskUtil) {
+ Class<? extends Task> taskClass = taskUtil.taskClass();
+ Class<? extends AbstractTaskTO> taskTOClass = taskUtil.taskTOClass();
+
+ if (taskClass == null || !taskClass.isAssignableFrom(task.getClass())) {
+ throw new IllegalArgumentException(
+ String.format("taskUtil is type %s but task is not: %s", taskClass, task.getClass()));
+ }
+
+ if (taskTOClass == null || !taskTOClass.equals(taskTO.getClass())) {
+ throw new IllegalArgumentException(
+ String.format("taskUtil is type %s but task is not: %s", taskTOClass, taskTO.getClass()));
+ }
+
+ task.setCronExpression(taskTO.getCronExpression());
+ if (StringUtils.isNotBlank(taskTO.getName())) {
+ task.setName(taskTO.getName());
+ }
+ if (StringUtils.isNotBlank(taskTO.getDescription())) {
+ task.setDescription(taskTO.getDescription());
+ }
+
+ if (task instanceof ProvisioningTask) {
+ fill((ProvisioningTask) task, (AbstractProvisioningTaskTO) taskTO);
+ }
+ }
+
+ @Override
+ public TaskExecTO getTaskExecTO(final TaskExec execution) {
+ TaskExecTO executionTO = new TaskExecTO();
+ BeanUtils.copyProperties(execution, executionTO, IGNORE_TASK_EXECUTION_PROPERTIES);
+
+ if (execution.getKey() != null) {
+ executionTO.setKey(execution.getKey());
+ }
+
+ if (execution.getTask() != null && execution.getTask().getKey() != null) {
+ executionTO.setTask(execution.getTask().getKey());
+ }
+
+ return executionTO;
+ }
+
+ private void setExecTime(final SchedTaskTO taskTO, final Task task) {
+ String triggerName = JobNamer.getTriggerName(JobNamer.getJobName(task));
+
+ Trigger trigger = null;
+ try {
+ trigger = scheduler.getScheduler().getTrigger(new TriggerKey(triggerName, Scheduler.DEFAULT_GROUP));
+ } catch (SchedulerException e) {
+ LOG.warn("While trying to get to " + triggerName, e);
+ }
+
+ if (trigger != null) {
+ taskTO.setLastExec(trigger.getPreviousFireTime());
+ taskTO.setNextExec(trigger.getNextFireTime());
+ }
+ }
+
+ @Override
+ public <T extends AbstractTaskTO> T getTaskTO(final Task task, final TaskUtil taskUtil) {
+ T taskTO = taskUtil.newTaskTO();
+ BeanUtils.copyProperties(task, taskTO, IGNORE_TASK_PROPERTIES);
+
+ TaskExec latestExec = taskExecDAO.findLatestStarted(task);
+ taskTO.setLatestExecStatus(latestExec == null ? "" : latestExec.getStatus());
+ taskTO.setStartDate(latestExec == null ? null : latestExec.getStartDate());
+ taskTO.setEndDate(latestExec == null ? null : latestExec.getEndDate());
+
+ for (TaskExec execution : task.getExecs()) {
+ taskTO.getExecutions().add(getTaskExecTO(execution));
+ }
+
+ switch (taskUtil.getType()) {
+ case PROPAGATION:
+ if (!(task instanceof PropagationTask)) {
+ throw new IllegalArgumentException("taskUtil is type Propagation but task is not PropagationTask: "
+ + task.getClass().getName());
+ }
+ ((PropagationTaskTO) taskTO).setResource(((PropagationTask) task).getResource().getKey());
+ break;
+
+ case SCHEDULED:
+ if (!(task instanceof SchedTask)) {
+ throw new IllegalArgumentException("taskUtil is type Sched but task is not SchedTask: "
+ + task.getClass().getName());
+ }
+ setExecTime((SchedTaskTO) taskTO, task);
+ ((SchedTaskTO) taskTO).setName(((SchedTask) task).getName());
+ ((SchedTaskTO) taskTO).setDescription(((SchedTask) task).getDescription());
+ break;
+
+ case SYNCHRONIZATION:
+ if (!(task instanceof SyncTask)) {
+ throw new IllegalArgumentException("taskUtil is type Sync but task is not SyncTask: "
+ + task.getClass().getName());
+ }
+ setExecTime((SchedTaskTO) taskTO, task);
+ ((SyncTaskTO) taskTO).setName(((SyncTask) task).getName());
+ ((SyncTaskTO) taskTO).setDescription(((SyncTask) task).getDescription());
+ ((SyncTaskTO) taskTO).setResource(((SyncTask) task).getResource().getKey());
+ ((SyncTaskTO) taskTO).setMatchingRule(((SyncTask) task).getMatchingRule() == null
+ ? MatchingRule.UPDATE : ((SyncTask) task).getMatchingRule());
+ ((SyncTaskTO) taskTO).setUnmatchingRule(((SyncTask) task).getUnmatchingRule() == null
+ ? UnmatchingRule.PROVISION : ((SyncTask) task).getUnmatchingRule());
+ break;
+
+ case PUSH:
+ if (!(task instanceof PushTask)) {
+ throw new IllegalArgumentException("taskUtil is type Push but task is not PushTask: "
+ + task.getClass().getName());
+ }
+ setExecTime((SchedTaskTO) taskTO, task);
+ ((PushTaskTO) taskTO).setName(((PushTask) task).getName());
+ ((PushTaskTO) taskTO).setDescription(((PushTask) task).getDescription());
+ ((PushTaskTO) taskTO).setResource(((PushTask) task).getResource().getKey());
+ ((PushTaskTO) taskTO).setMatchingRule(((PushTask) task).getMatchingRule() == null
+ ? MatchingRule.LINK : ((PushTask) task).getMatchingRule());
+ ((PushTaskTO) taskTO).setUnmatchingRule(((PushTask) task).getUnmatchingRule() == null
+ ? UnmatchingRule.ASSIGN : ((PushTask) task).getUnmatchingRule());
+ break;
+
+ case NOTIFICATION:
+ if (((NotificationTask) task).isExecuted() && StringUtils.isBlank(taskTO.getLatestExecStatus())) {
+ taskTO.setLatestExecStatus("[EXECUTED]");
+ }
+ break;
+
+ default:
+ }
+
+ return taskTO;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/d30c8526/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java b/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
new file mode 100644
index 0000000..af6dbb6
--- /dev/null
+++ b/syncope620/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
@@ -0,0 +1,411 @@
+/*
+ * 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.provisioning.java.data;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.Resource;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.SyncopeClientCompositeException;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.mod.MembershipMod;
+import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.CipherAlgorithm;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.core.persistence.api.dao.ConfDAO;
+import org.apache.syncope.core.persistence.api.dao.SecurityQuestionDAO;
+import org.apache.syncope.core.persistence.api.entity.DerAttr;
+import org.apache.syncope.core.persistence.api.entity.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.VirAttr;
+import org.apache.syncope.core.persistence.api.entity.membership.MDerAttr;
+import org.apache.syncope.core.persistence.api.entity.membership.MPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.membership.MVirAttr;
+import org.apache.syncope.core.persistence.api.entity.membership.Membership;
+import org.apache.syncope.core.persistence.api.entity.role.Role;
+import org.apache.syncope.core.persistence.api.entity.user.SecurityQuestion;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.common.lib.types.PropagationByResource;
+import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
+import org.apache.syncope.core.misc.security.AuthContextUtil;
+import org.apache.syncope.core.misc.security.Encryptor;
+import org.apache.syncope.core.misc.spring.BeanUtils;
+import org.apache.syncope.core.misc.ConnObjectUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+@Component
+@Transactional(rollbackFor = { Throwable.class })
+public class UserDataBinderImpl extends AbstractAttributableDataBinder implements UserDataBinder {
+
+ private static final String[] IGNORE_USER_PROPERTIES = {
+ "memberships", "plainAttrs", "derAttrs", "virAttrs", "resources", "securityQuestion", "securityAnswer"
+ };
+
+ @Autowired
+ private ConfDAO confDAO;
+
+ @Autowired
+ private ConnObjectUtil connObjectUtil;
+
+ @Autowired
+ private SecurityQuestionDAO securityQuestionDAO;
+
+ @Resource(name = "adminUser")
+ private String adminUser;
+
+ @Resource(name = "anonymousUser")
+ private String anonymousUser;
+
+ private final Encryptor encryptor = Encryptor.getInstance();
+
+ @Transactional(readOnly = true)
+ @Override
+ public UserTO getAuthenticatedUserTO() {
+ final UserTO authUserTO;
+
+ final String authUsername = AuthContextUtil.getAuthenticatedUsername();
+ if (anonymousUser.equals(authUsername)) {
+ authUserTO = new UserTO();
+ authUserTO.setKey(-2);
+ authUserTO.setUsername(anonymousUser);
+ } else if (adminUser.equals(authUsername)) {
+ authUserTO = new UserTO();
+ authUserTO.setKey(-1);
+ authUserTO.setUsername(adminUser);
+ } else {
+ User authUser = userDAO.find(authUsername);
+ authUserTO = getUserTO(authUser);
+ }
+
+ return authUserTO;
+ }
+
+ @Transactional(readOnly = true)
+ @Override
+ public boolean verifyPassword(final String username, final String password) {
+ return verifyPassword(userDAO.authFetch(username), password);
+ }
+
+ @Transactional(readOnly = true)
+ @Override
+ public boolean verifyPassword(final User user, final String password) {
+ return encryptor.verify(password, user.getCipherAlgorithm(), user.getPassword());
+ }
+
+ private void setPassword(final User user, final String password,
+ final SyncopeClientCompositeException scce) {
+
+ try {
+ final String algorithm = confDAO.find(
+ "password.cipher.algorithm", CipherAlgorithm.AES.name()).getValues().get(0).getStringValue();
+ CipherAlgorithm predefined = CipherAlgorithm.valueOf(algorithm);
+ user.setPassword(password, predefined);
+ } catch (IllegalArgumentException e) {
+ final SyncopeClientException invalidCiperAlgorithm =
+ SyncopeClientException.build(ClientExceptionType.NotFound);
+ invalidCiperAlgorithm.getElements().add(e.getMessage());
+ scce.addException(invalidCiperAlgorithm);
+
+ throw scce;
+ }
+ }
+
+ @Override
+ public void create(final User user, final UserTO userTO, final boolean storePassword) {
+ SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
+
+ // memberships
+ Role role;
+ for (MembershipTO membershipTO : userTO.getMemberships()) {
+ role = roleDAO.find(membershipTO.getRoleId());
+
+ if (role == null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Ignoring invalid role " + membershipTO.getRoleName());
+ }
+ } else {
+ Membership membership = null;
+ if (user.getKey() != null) {
+ membership = user.getMembership(role.getKey()) == null
+ ? membershipDAO.find(user, role)
+ : user.getMembership(role.getKey());
+ }
+ if (membership == null) {
+ membership = entityFactory.newEntity(Membership.class);
+ membership.setRole(role);
+ membership.setUser(user);
+
+ user.addMembership(membership);
+ }
+
+ fill(membership, membershipTO, attrUtilFactory.getInstance(AttributableType.MEMBERSHIP), scce);
+ }
+ }
+
+ // attributes, derived attributes, virtual attributes and resources
+ fill(user, userTO, attrUtilFactory.getInstance(AttributableType.USER), scce);
+
+ // set password
+ if (StringUtils.isBlank(userTO.getPassword()) || !storePassword) {
+ LOG.debug("Password was not provided or not required to be stored");
+ } else {
+ setPassword(user, userTO.getPassword(), scce);
+ }
+
+ // set username
+ user.setUsername(userTO.getUsername());
+
+ // security question / answer
+ if (userTO.getSecurityQuestion() != null) {
+ SecurityQuestion securityQuestion = securityQuestionDAO.find(userTO.getSecurityQuestion());
+ if (securityQuestion != null) {
+ user.setSecurityQuestion(securityQuestion);
+ }
+ }
+ user.setSecurityAnswer(userTO.getSecurityAnswer());
+ }
+
+ /**
+ * Update user, given UserMod.
+ *
+ * @param toBeUpdated user to be updated
+ * @param userMod bean containing update request
+ * @return updated user + propagation by resource
+ * @see PropagationByResource
+ */
+ @Override
+ public PropagationByResource update(final User toBeUpdated, final UserMod userMod) {
+ // Re-merge any pending change from workflow tasks
+ User user = userDAO.save(toBeUpdated);
+
+ PropagationByResource propByRes = new PropagationByResource();
+
+ SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
+
+ Set<String> currentResources = user.getResourceNames();
+
+ // fetch account ids before update
+ Map<String, String> oldAccountIds = getAccountIds(user, AttributableType.USER);
+
+ // password
+ if (StringUtils.isNotBlank(userMod.getPassword())) {
+ setPassword(user, userMod.getPassword(), scce);
+ user.setChangePwdDate(new Date());
+ propByRes.addAll(ResourceOperation.UPDATE, currentResources);
+ }
+
+ // username
+ if (userMod.getUsername() != null && !userMod.getUsername().equals(user.getUsername())) {
+ propByRes.addAll(ResourceOperation.UPDATE, currentResources);
+
+ user.setUsername(userMod.getUsername());
+ }
+
+ // security question / answer:
+ // userMod.getSecurityQuestion() is null => remove user security question and answer
+ // userMod.getSecurityQuestion() == 0 => don't change anything
+ // userMod.getSecurityQuestion() > 0 => update user security question and answer
+ if (userMod.getSecurityQuestion() == null) {
+ user.setSecurityQuestion(null);
+ user.setSecurityAnswer(null);
+ } else if (userMod.getSecurityQuestion() > 0) {
+ SecurityQuestion securityQuestion = securityQuestionDAO.find(userMod.getSecurityQuestion());
+ if (securityQuestion != null) {
+ user.setSecurityQuestion(securityQuestion);
+ user.setSecurityAnswer(userMod.getSecurityAnswer());
+ }
+ }
+
+ // attributes, derived attributes, virtual attributes and resources
+ propByRes.merge(fill(user, userMod, attrUtilFactory.getInstance(AttributableType.USER), scce));
+
+ // store the role ids of membership required to be added
+ Set<Long> membershipToBeAddedRoleIds = new HashSet<>();
+ for (MembershipMod membToBeAdded : userMod.getMembershipsToAdd()) {
+ membershipToBeAddedRoleIds.add(membToBeAdded.getRole());
+ }
+
+ final Set<String> toBeDeprovisioned = new HashSet<>();
+ final Set<String> toBeProvisioned = new HashSet<>();
+
+ // memberships to be removed
+ for (Long membershipId : userMod.getMembershipsToRemove()) {
+ LOG.debug("Membership to be removed: {}", membershipId);
+
+ Membership membership = membershipDAO.find(membershipId);
+ if (membership == null) {
+ LOG.debug("Invalid membership id specified to be removed: {}", membershipId);
+ } else {
+ if (!membershipToBeAddedRoleIds.contains(membership.getRole().getKey())) {
+ toBeDeprovisioned.addAll(membership.getRole().getResourceNames());
+ }
+
+ // In order to make the removeMembership() below to work,
+ // we need to be sure to take exactly the same membership
+ // of the user object currently in memory (which has potentially
+ // some modifications compared to the one stored in the DB
+ membership = user.getMembership(membership.getRole().getKey());
+ if (membershipToBeAddedRoleIds.contains(membership.getRole().getKey())) {
+ Set<Long> attributeIds = new HashSet<>(membership.getPlainAttrs().size());
+ for (PlainAttr attribute : membership.getPlainAttrs()) {
+ attributeIds.add(attribute.getKey());
+ }
+ for (Long attributeId : attributeIds) {
+ plainAttrDAO.delete(attributeId, MPlainAttr.class);
+ }
+ attributeIds.clear();
+
+ // remove derived attributes
+ for (DerAttr derAttr : membership.getDerAttrs()) {
+ attributeIds.add(derAttr.getKey());
+ }
+ for (Long derAttrId : attributeIds) {
+ derAttrDAO.delete(derAttrId, MDerAttr.class);
+ }
+ attributeIds.clear();
+
+ // remove virtual attributes
+ for (VirAttr virAttr : membership.getVirAttrs()) {
+ attributeIds.add(virAttr.getKey());
+ }
+ for (Long virAttrId : attributeIds) {
+ virAttrDAO.delete(virAttrId, MVirAttr.class);
+ }
+ attributeIds.clear();
+ } else {
+ user.removeMembership(membership);
+
+ membershipDAO.delete(membershipId);
+ }
+ }
+ }
+
+ // memberships to be added
+ for (MembershipMod membershipMod : userMod.getMembershipsToAdd()) {
+ LOG.debug("Membership to be added: role({})", membershipMod.getRole());
+
+ Role role = roleDAO.find(membershipMod.getRole());
+ if (role == null) {
+ LOG.debug("Ignoring invalid role {}", membershipMod.getRole());
+ } else {
+ Membership membership = user.getMembership(role.getKey());
+ if (membership == null) {
+ membership = entityFactory.newEntity(Membership.class);
+ membership.setRole(role);
+ membership.setUser(user);
+
+ user.addMembership(membership);
+
+ toBeProvisioned.addAll(role.getResourceNames());
+ }
+
+ propByRes.merge(fill(membership, membershipMod,
+ attrUtilFactory.getInstance(AttributableType.MEMBERSHIP), scce));
+ }
+ }
+
+ propByRes.addAll(ResourceOperation.DELETE, toBeDeprovisioned);
+ propByRes.addAll(ResourceOperation.UPDATE, toBeProvisioned);
+
+ /**
+ * In case of new memberships all the current resources have to be updated in order to propagate new role and
+ * membership attribute values.
+ */
+ if (!toBeDeprovisioned.isEmpty() || !toBeProvisioned.isEmpty()) {
+ currentResources.removeAll(toBeDeprovisioned);
+ propByRes.addAll(ResourceOperation.UPDATE, currentResources);
+ }
+
+ // check if some account id was changed by the update above
+ Map<String, String> newAccountIds = getAccountIds(user, AttributableType.USER);
+ for (Map.Entry<String, String> entry : oldAccountIds.entrySet()) {
+ if (newAccountIds.containsKey(entry.getKey())
+ && !entry.getValue().equals(newAccountIds.get(entry.getKey()))) {
+
+ propByRes.addOldAccountId(entry.getKey(), entry.getValue());
+ propByRes.add(ResourceOperation.UPDATE, entry.getKey());
+ }
+ }
+
+ return propByRes;
+ }
+
+ @Transactional(readOnly = true)
+ @Override
+ public UserTO getUserTO(final User user) {
+ UserTO userTO = new UserTO();
+
+ BeanUtils.copyProperties(user, userTO, IGNORE_USER_PROPERTIES);
+
+ if (user.getSecurityQuestion() != null) {
+ userTO.setSecurityQuestion(user.getSecurityQuestion().getKey());
+ }
+
+ connObjectUtil.retrieveVirAttrValues(user, attrUtilFactory.getInstance(AttributableType.USER));
+ fillTO(userTO, user.getPlainAttrs(), user.getDerAttrs(), user.getVirAttrs(), user.getResources());
+
+ MembershipTO membershipTO;
+ for (Membership membership : user.getMemberships()) {
+ membershipTO = new MembershipTO();
+
+ // set sys info
+ membershipTO.setCreator(membership.getCreator());
+ membershipTO.setCreationDate(membership.getCreationDate());
+ membershipTO.setLastModifier(membership.getLastModifier());
+ membershipTO.setLastChangeDate(membership.getLastChangeDate());
+
+ membershipTO.setKey(membership.getKey());
+ membershipTO.setRoleId(membership.getRole().getKey());
+ membershipTO.setRoleName(membership.getRole().getName());
+
+ // SYNCOPE-458 retrieve also membership virtual attributes
+ connObjectUtil.retrieveVirAttrValues(membership, attrUtilFactory.getInstance(AttributableType.MEMBERSHIP));
+
+ fillTO(membershipTO,
+ membership.getPlainAttrs(), membership.getDerAttrs(), membership.getVirAttrs(),
+ Collections.<ExternalResource>emptyList());
+
+ userTO.getMemberships().add(membershipTO);
+ }
+
+ return userTO;
+ }
+
+ @Transactional(readOnly = true)
+ @Override
+ public UserTO getUserTO(final String username) {
+ return getUserTO(userDAO.authFetch(username));
+ }
+
+ @Transactional(readOnly = true)
+ @Override
+ public UserTO getUserTO(final Long key) {
+ return getUserTO(userDAO.authFetch(key));
+ }
+
+}