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 2020/02/14 09:33:40 UTC
[syncope] branch master updated: [SYNCOPE-1535] Provision Sorter
Implementation (#166)
This is an automated email from the ASF dual-hosted git repository.
ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/master by this push:
new bdd1023 [SYNCOPE-1535] Provision Sorter Implementation (#166)
bdd1023 is described below
commit bdd102378669407fca7885e0b0e39c1bf3b7205e
Author: DimaAy <di...@tirasa.net>
AuthorDate: Fri Feb 14 09:32:26 2020 +0100
[SYNCOPE-1535] Provision Sorter Implementation (#166)
* [SYNCOPE-1535] Provision Sorter Implementation
* [SYNCOPE-1535] resolve sort
* solve checkStyle
---
.../commons/IdMImplementationInfoProvider.java | 8 +-
.../wizards/resources/ResourceDetailsPanel.java | 16 +++
.../wizards/resources/ResourceDetailsPanel.html | 4 +
.../resources/ResourceDetailsPanel.properties | 1 +
.../ResourceDetailsPanel_fr_CA.properties | 9 +-
.../resources/ResourceDetailsPanel_it.properties | 1 +
.../resources/ResourceDetailsPanel_ja.properties | 1 +
.../ResourceDetailsPanel_pt_BR.properties | 1 +
.../resources/ResourceDetailsPanel_ru.properties | 1 +
.../implementations/MyProvisionSorter.groovy | 33 +++++
.../apache/syncope/common/lib/to/ResourceTO.java | 10 ++
.../common/lib/types/IdMImplementationType.java | 5 +-
.../init/ClassPathScanImplementationLookup.java | 5 +
.../api/entity/resource/ExternalResource.java | 4 +
.../jpa/entity/resource/JPAExternalResource.java | 15 ++
.../core/provisioning/api/ProvisionSorter.java | 26 ++++
.../provisioning/java/DefaultProvisionSorter.java | 45 ++++++
.../java/data/ImplementationDataBinderImpl.java | 5 +
.../java/data/ResourceDataBinderImpl.java | 15 ++
.../java/pushpull/PullJobDelegate.java | 155 +++++++++++----------
.../fit/core/reference/ITImplementationLookup.java | 8 ++
.../view/ResourceExplorerTopComponent.java | 10 +-
22 files changed, 296 insertions(+), 82 deletions(-)
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMImplementationInfoProvider.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMImplementationInfoProvider.java
index 1ceacaf..174c813 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMImplementationInfoProvider.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMImplementationInfoProvider.java
@@ -68,7 +68,7 @@ public class IdMImplementationInfoProvider extends IdRepoImplementationInfoProvi
@Override
public String getGroovyTemplateClassName(final String implementationType) {
- String templateClassName = null;
+ String templateClassName;
switch (implementationType) {
case IdMImplementationType.ITEM_TRANSFORMER:
@@ -99,6 +99,10 @@ public class IdMImplementationInfoProvider extends IdRepoImplementationInfoProvi
templateClassName = "MyPushCorrelationRule";
break;
+ case IdMImplementationType.PROVISION_SORTER:
+ templateClassName = "MyProvisionSorter";
+ break;
+
default:
templateClassName = super.getGroovyTemplateClassName(implementationType);
}
@@ -108,7 +112,7 @@ public class IdMImplementationInfoProvider extends IdRepoImplementationInfoProvi
@Override
public Class<?> getClass(final String implementationType, final String name) {
- Class<?> clazz = null;
+ Class<?> clazz;
switch (implementationType) {
case IdMImplementationType.PULL_CORRELATION_RULE:
clazz = lookup.getPullCorrelationRuleConfs().get(name);
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.java
index f326f76..2023c99 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.java
@@ -56,6 +56,17 @@ public class ResourceDetailsPanel extends WizardStep {
}
};
+ private final IModel<List<String>> provisionSorters = new LoadableDetachableModel<List<String>>() {
+
+ private static final long serialVersionUID = 4659376149825914247L;
+
+ @Override
+ protected List<String> load() {
+ return ImplementationRestClient.list(IdMImplementationType.PROVISION_SORTER).stream().
+ map(EntityTO::getKey).sorted().collect(Collectors.toList());
+ }
+ };
+
public ResourceDetailsPanel(final ResourceTO resourceTO, final boolean createFlag) {
super();
setOutputMarkupId(true);
@@ -103,6 +114,11 @@ public class ResourceDetailsPanel extends WizardStep {
setChoices(Arrays.stream(TraceLevel.values()).collect(Collectors.toList())).setNullValid(false));
container.add(new AjaxDropDownChoicePanel<>(
+ "provisionSorter", "provisionSorter",
+ new PropertyModel<>(resourceTO, "provisionSorter"), false).
+ setChoices(provisionSorters));
+
+ container.add(new AjaxDropDownChoicePanel<>(
"updateTraceLevel",
new ResourceModel("updateTraceLevel", "updateTraceLevel").getObject(),
new PropertyModel<>(resourceTO, "updateTraceLevel"),
diff --git a/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.html b/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.html
index c730e84..6dd792c 100644
--- a/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.html
+++ b/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.html
@@ -44,6 +44,10 @@ under the License.
</div>
<div class="form-group">
+ <span wicket:id="provisionSorter">[provisionSorter]</span>
+ </div>
+
+ <div class="form-group">
<span wicket:id="createTraceLevel">[createTraceLevel]</span>
</div>
diff --git a/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.properties b/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.properties
index 5e588e5..004dd02 100644
--- a/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.properties
+++ b/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.properties
@@ -20,6 +20,7 @@ enforceMandatoryCondition=Enforce mandatory condition
propagationPriority=Propagation priority
randomPwdIfNotProvided=Generate random passwords when missing
propagationActions=Propagation Actions
+provisionSorter=Provision Sorter
createTraceLevel=Propagation: create trace level
updateTraceLevel=Propagation: update trace level
deleteTraceLevel=Propagation: delete trace level
diff --git a/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_fr_CA.properties b/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_fr_CA.properties
index cd93a42..587a5f2 100644
--- a/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_fr_CA.properties
+++ b/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_fr_CA.properties
@@ -17,10 +17,11 @@
name=Nom de la ressource
connector=Raccordement
enforceMandatoryCondition=Application de la condition obligatoire
-propagationPriority=Priorit� de propagation
-randomPwdIfNotProvided=G�n�rer des mots de passe al�atoires si manquants.
+propagationPriority=Priorit\u00e9 de propagation
+randomPwdIfNotProvided=G\u00e9n\u00e9rer des mots de passe al\u00e9atoires si manquants.
propagationActions=Actions de propagation
-createTraceLevel=Propagation : cr�ation d'un niveau de trace
-updateTraceLevel=Propagation : mise � jour du niveau de trace
+provisionSorter=Trieur de provision
+createTraceLevel=Propagation : cr\u00e9ation d'un niveau de trace
+updateTraceLevel=Propagation : mise \u00e0 jour du niveau de trace
deleteTraceLevel=Propagation : effacer le niveau de trace
provisioningTraceLevel=Push/pull le niveau de trace
diff --git a/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_it.properties b/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_it.properties
index 33422f1..3d69ca0 100644
--- a/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_it.properties
+++ b/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_it.properties
@@ -20,6 +20,7 @@ enforceMandatoryCondition=Abilita mandatory condition
propagationPriority=Priorit\u00e0 in propagazione
randomPwdIfNotProvided=Genera password casuali se mancanti
propagationActions=Azioni di Propagazione
+provisionSorter=Provision Sorter
createTraceLevel=Propagazione: tracciamento creazione
updateTraceLevel=Propagazione: tracciamento aggiornamento
deleteTraceLevel=Propagazione: tracciamento rimozione
diff --git a/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_ja.properties b/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_ja.properties
index 7636f94..477b0e8 100644
--- a/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_ja.properties
+++ b/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_ja.properties
@@ -20,6 +20,7 @@ enforceMandatoryCondition=\u5fc5\u9808\u6761\u4ef6\u306b\u5f93\u3046
propagationPriority=\u4f1d\u64ad\u512a\u5148\u5ea6
randomPwdIfNotProvided=\u898b\u3064\u304b\u3089\u306a\u3044\u5834\u5408\u306f\u30e9\u30f3\u30c0\u30e0\u306a\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u751f\u6210
propagationActions=\u4f1d\u64ad\u30a2\u30af\u30b7\u30e7\u30f3
+provisionSorter=\u30bd\u30fc\u30bf\u30fc\u306e\u30d7\u30ed\u30d3\u30b8\u30e7\u30cb\u30f3\u30b0
createTraceLevel=\u4f1d\u64ad: \u4f5c\u6210\u30c8\u30ec\u30fc\u30b9\u30ec\u30d9\u30eb
updateTraceLevel=\u4f1d\u64ad: \u66f4\u65b0\u30c8\u30ec\u30fc\u30b9\u30ec\u30d9\u30eb
deleteTraceLevel=\u4f1d\u64ad: \u524a\u9664\u30c8\u30ec\u30fc\u30b9\u30ec\u30d9\u30eb
diff --git a/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_pt_BR.properties b/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_pt_BR.properties
index d2c7119..79ac8ed 100644
--- a/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_pt_BR.properties
+++ b/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_pt_BR.properties
@@ -20,6 +20,7 @@ enforceMandatoryCondition=Aplicar condi\u00e7\u00e3o obrigat\u00f3ria
propagationPriority=Prioridade de propaga\u00e7\u00e3o
randomPwdIfNotProvided=Gerar senhas aleat\u00f3rias quando n\u00e3o houver
propagationActions=A\u00e7\u00f5es de Propaga\u00e7\u00e3o
+provisionSorter=Classificador de Provis\u00f5es
createTraceLevel=Propagation: create trace level
updateTraceLevel=Propagation: update trace level
deleteTraceLevel=Propagation: delete trace level
diff --git a/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_ru.properties b/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_ru.properties
index 2340913..c2ef730 100644
--- a/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_ru.properties
+++ b/client/idm/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel_ru.properties
@@ -21,6 +21,7 @@ enforceMandatoryCondition=\u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c
propagationPriority=\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439
randomPwdIfNotProvided=\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c, \u0435\u0441\u043b\u0438 \u043e\u043d \u043d\u0435 \u0437\u0430\u0434\u0430\u043d
propagationActions=\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f
+provisionSorter=\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a \u043f\u0440\u043e\u0432\u0438\u0437\u0438\u0438
createTraceLevel=\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439: \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043f\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e
updateTraceLevel=\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439: \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043f\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044e
deleteTraceLevel=\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439: \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043f\u043e \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044e
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/implementations/MyProvisionSorter.groovy b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/implementations/MyProvisionSorter.groovy
new file mode 100644
index 0000000..c59a91c
--- /dev/null
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/implementations/MyProvisionSorter.groovy
@@ -0,0 +1,33 @@
+
+/*
+ * 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.
+ */
+import groovy.transform.CompileStatic
+import org.apache.syncope.core.persistence.api.ProvisionSorter
+import org.apache.syncope.core.persistence.api.entity.resource.Provision
+
+
+@CompileStatic
+class MyProvisionSorter implements ProvisionSorter {
+
+ @Override
+ int compare(Provision provision1, Provision provision2) {
+ return 0;
+ }
+
+}
\ No newline at end of file
diff --git a/common/idm/lib/src/main/java/org/apache/syncope/common/lib/to/ResourceTO.java b/common/idm/lib/src/main/java/org/apache/syncope/common/lib/to/ResourceTO.java
index 8581d54..20a8628 100644
--- a/common/idm/lib/src/main/java/org/apache/syncope/common/lib/to/ResourceTO.java
+++ b/common/idm/lib/src/main/java/org/apache/syncope/common/lib/to/ResourceTO.java
@@ -80,6 +80,8 @@ public class ResourceTO implements EntityTO {
private String pushPolicy;
+ private String provisionSorter;
+
private final List<ConnConfProperty> confOverride = new ArrayList<>();
private boolean overrideCapabilities = false;
@@ -195,6 +197,14 @@ public class ResourceTO implements EntityTO {
this.pushPolicy = pushPolicy;
}
+ public String getProvisionSorter() {
+ return provisionSorter;
+ }
+
+ public void setProvisionSorter(final String provisionSorter) {
+ this.provisionSorter = provisionSorter;
+ }
+
@JsonIgnore
public Optional<ProvisionTO> getProvision(final String anyType) {
return provisions.stream().filter(
diff --git a/common/idm/lib/src/main/java/org/apache/syncope/common/lib/types/IdMImplementationType.java b/common/idm/lib/src/main/java/org/apache/syncope/common/lib/types/IdMImplementationType.java
index f8cc797..a3aff0a 100644
--- a/common/idm/lib/src/main/java/org/apache/syncope/common/lib/types/IdMImplementationType.java
+++ b/common/idm/lib/src/main/java/org/apache/syncope/common/lib/types/IdMImplementationType.java
@@ -37,6 +37,8 @@ public final class IdMImplementationType {
public static final String PUSH_CORRELATION_RULE = "PUSH_CORRELATION_RULE";
+ public static final String PROVISION_SORTER = "PROVISION_SORTER";
+
private static final Map<String, String> VALUES = Map.ofEntries(
Pair.of(ITEM_TRANSFORMER, "org.apache.syncope.core.spring.security.JWTSSOProvider"),
Pair.of(RECON_FILTER_BUILDER, "org.apache.syncope.core.persistence.api.dao.Reportlet"),
@@ -44,7 +46,8 @@ public final class IdMImplementationType {
Pair.of(PULL_ACTIONS, "org.apache.syncope.core.persistence.api.dao.PasswordRule"),
Pair.of(PUSH_ACTIONS, "org.apache.syncope.core.provisioning.api.job.SchedTaskJobDelegate"),
Pair.of(PULL_CORRELATION_RULE, "org.apache.syncope.core.provisioning.api.LogicActions"),
- Pair.of(PUSH_CORRELATION_RULE, "org.apache.syncope.core.persistence.api.attrvalue.validation.Validator"));
+ Pair.of(PUSH_CORRELATION_RULE, "org.apache.syncope.core.persistence.api.attrvalue.validation.Validator"),
+ Pair.of(PROVISION_SORTER, "org.apache.syncope.core.provisioning.api.ProvisionSorter"));
public static Map<String, String> values() {
return VALUES;
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
index 446a7db..5baf2e5 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
@@ -53,6 +53,7 @@ import org.apache.syncope.core.persistence.api.dao.PullCorrelationRule;
import org.apache.syncope.core.persistence.api.dao.PullCorrelationRuleConfClass;
import org.apache.syncope.core.persistence.api.dao.PushCorrelationRule;
import org.apache.syncope.core.persistence.api.dao.PushCorrelationRuleConfClass;
+import org.apache.syncope.core.provisioning.api.ProvisionSorter;
import org.apache.syncope.core.provisioning.api.pushpull.PushActions;
import org.apache.syncope.core.provisioning.api.pushpull.ReconFilterBuilder;
import org.apache.syncope.core.provisioning.java.data.JEXLItemTransformerImpl;
@@ -238,6 +239,10 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
classNames.get(IdRepoImplementationType.AUDIT_APPENDER).add(clazz.getName());
auditAppenderClasses.add(clazz);
}
+
+ if (ProvisionSorter.class.isAssignableFrom(clazz) && !isAbstractClazz) {
+ classNames.get(IdMImplementationType.PROVISION_SORTER).add(bd.getBeanClassName());
+ }
} catch (Throwable t) {
LOG.warn("Could not inspect class {}", bd.getBeanClassName(), t);
}
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/ExternalResource.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/ExternalResource.java
index 0d91ed0..1bb44d9 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/ExternalResource.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/ExternalResource.java
@@ -63,6 +63,10 @@ public interface ExternalResource extends ProvidedKeyEntity {
void setPullPolicy(PullPolicy pullPolicy);
PushPolicy getPushPolicy();
+
+ Implementation getProvisionSorter();
+
+ void setProvisionSorter(Implementation provisionSorter);
void setPushPolicy(PushPolicy pushPolicy);
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java
index e61568e..ef97aa6 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java
@@ -136,6 +136,9 @@ public class JPAExternalResource extends AbstractProvidedKeyEntity implements Ex
@ManyToOne(fetch = FetchType.EAGER)
private JPAPushPolicy pushPolicy;
+ @ManyToOne
+ private JPAImplementation provisionSorter;
+
/**
* Configuration properties that are overridden from the connector instance.
*/
@@ -330,6 +333,18 @@ public class JPAExternalResource extends AbstractProvidedKeyEntity implements Ex
}
@Override
+ public Implementation getProvisionSorter() {
+ return provisionSorter;
+ }
+
+ @Override
+ public void setProvisionSorter(final Implementation provisionSorter) {
+ checkType(provisionSorter, JPAImplementation.class);
+ checkImplementationType(provisionSorter, IdMImplementationType.PROVISION_SORTER);
+ this.provisionSorter = (JPAImplementation) provisionSorter;
+ }
+
+ @Override
public Set<ConnConfProperty> getConfOverride() {
Set<ConnConfProperty> confOverride = new HashSet<>();
if (!StringUtils.isBlank(jsonConf)) {
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/ProvisionSorter.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/ProvisionSorter.java
new file mode 100644
index 0000000..ad9d3a1
--- /dev/null
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/ProvisionSorter.java
@@ -0,0 +1,26 @@
+/*
+ * 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.api;
+
+import java.util.Comparator;
+import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+
+public interface ProvisionSorter extends Comparator<Provision> {
+
+}
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultProvisionSorter.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultProvisionSorter.java
new file mode 100644
index 0000000..0acd40d
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultProvisionSorter.java
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+import org.apache.syncope.core.provisioning.api.ProvisionSorter;
+
+public class DefaultProvisionSorter implements ProvisionSorter {
+
+ @Override
+ public int compare(final Provision provision1, final Provision provision2) {
+ if (provision1.getAnyType().getKind() == AnyTypeKind.USER) {
+ return -1;
+ }
+ if (provision2.getAnyType().getKind() == AnyTypeKind.USER) {
+ return 1;
+ }
+ if (provision1.getAnyType().getKind() == AnyTypeKind.GROUP) {
+ return -1;
+ }
+ if (provision2.getAnyType().getKind() == AnyTypeKind.GROUP) {
+ return 1;
+ }
+ return ObjectUtils.compare(provision1.getAnyType().getKey(), provision2.getAnyType().getKey());
+ }
+
+}
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ImplementationDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ImplementationDataBinderImpl.java
index 1b530a3..0cfe2ff 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ImplementationDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ImplementationDataBinderImpl.java
@@ -42,6 +42,7 @@ import org.apache.syncope.core.provisioning.api.propagation.PropagationActions;
import org.apache.syncope.core.provisioning.api.pushpull.PullActions;
import org.apache.syncope.core.persistence.api.dao.PullCorrelationRule;
import org.apache.syncope.core.persistence.api.dao.PushCorrelationRule;
+import org.apache.syncope.core.provisioning.api.ProvisionSorter;
import org.apache.syncope.core.provisioning.api.notification.RecipientsProvider;
import org.apache.syncope.core.provisioning.api.pushpull.PushActions;
import org.apache.syncope.core.provisioning.api.pushpull.ReconFilterBuilder;
@@ -144,6 +145,10 @@ public class ImplementationDataBinderImpl implements ImplementationDataBinder {
base = RecipientsProvider.class;
break;
+ case IdMImplementationType.PROVISION_SORTER:
+ base = ProvisionSorter.class;
+ break;
+
default:
}
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
index 96dad29..1df550e 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
@@ -358,6 +358,18 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
resource.setPushPolicy(resourceTO.getPushPolicy() == null
? null : (PushPolicy) policyDAO.find(resourceTO.getPushPolicy()));
+ if (resourceTO.getProvisionSorter() == null) {
+ resource.setProvisionSorter(null);
+ } else {
+ Implementation provisionSorter = implementationDAO.find(resourceTO.getProvisionSorter());
+ if (provisionSorter == null) {
+ LOG.debug("Invalid " + Implementation.class.getSimpleName() + " {}, ignoring...",
+ resourceTO.getProvisionSorter());
+ } else {
+ resource.setProvisionSorter(provisionSorter);
+ }
+ }
+
resource.setConfOverride(new HashSet<>(resourceTO.getConfOverride()));
resource.setOverrideCapabilities(resourceTO.isOverrideCapabilities());
@@ -675,6 +687,9 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
resourceTO.setPushPolicy(resource.getPushPolicy() == null
? null : resource.getPushPolicy().getKey());
+ resourceTO.setProvisionSorter(resource.getProvisionSorter() == null
+ ? null : resource.getProvisionSorter().getKey());
+
resourceTO.getConfOverride().addAll(resource.getConfOverride());
Collections.sort(resourceTO.getConfOverride());
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
index 74c935e..ded6b13 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.common.lib.types.ConflictResolutionAction;
@@ -49,6 +50,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.apache.syncope.core.persistence.api.entity.task.PullTask;
import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.provisioning.api.ProvisionSorter;
import org.apache.syncope.core.provisioning.api.pushpull.AnyObjectPullResultHandler;
import org.apache.syncope.core.provisioning.api.pushpull.PullActions;
import org.apache.syncope.core.provisioning.api.pushpull.GroupPullResultHandler;
@@ -62,6 +64,7 @@ import org.identityconnectors.framework.common.objects.ObjectClass;
import org.identityconnectors.framework.common.objects.OperationOptions;
import org.identityconnectors.framework.common.objects.SyncToken;
import org.apache.syncope.core.provisioning.api.pushpull.ReconFilterBuilder;
+import org.apache.syncope.core.provisioning.java.DefaultProvisionSorter;
import org.apache.syncope.core.spring.ImplementationManager;
public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> implements SyncopePullExecutor {
@@ -270,89 +273,99 @@ public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> i
}
}
+ ProvisionSorter provisionSorter = new DefaultProvisionSorter();
+ if (pullTask.getResource().getProvisionSorter() != null) {
+ try {
+ provisionSorter = ImplementationManager.build(pullTask.getResource().getProvisionSorter());
+ } catch (Exception e) {
+ LOG.error("While building {}", pullTask.getResource().getProvisionSorter(), e);
+ }
+ }
// ...then provisions for any types
SyncopePullResultHandler handler;
GroupPullResultHandler ghandler = buildGroupHandler();
- for (Provision provision : pullTask.getResource().getProvisions()) {
- if (provision.getMapping() != null) {
- status.set("Pulling " + provision.getObjectClass().getObjectClassValue());
+ for (Provision provision : pullTask.getResource().getProvisions().stream().
+ filter(provision -> provision.getMapping() != null).sorted(provisionSorter).
+ collect(Collectors.toList())) {
+
+ status.set("Pulling " + provision.getObjectClass().getObjectClassValue());
- switch (provision.getAnyType().getKind()) {
- case USER:
- handler = buildUserHandler();
+ switch (provision.getAnyType().getKind()) {
+ case USER:
+ handler = buildUserHandler();
+ break;
+
+ case GROUP:
+ handler = ghandler;
+ break;
+
+ case ANY_OBJECT:
+ default:
+ handler = buildAnyObjectHandler();
+ }
+ handler.setProfile(profile);
+ handler.setPullExecutor(this);
+
+ try {
+ Set<String> moreAttrsToGet = new HashSet<>();
+ actions.forEach(action -> moreAttrsToGet.addAll(action.moreAttrsToGet(profile, provision)));
+
+ Stream<? extends Item> mapItems = Stream.concat(
+ MappingUtils.getPullItems(provision.getMapping().getItems().stream()),
+ virSchemaDAO.findByProvision(provision).stream().map(VirSchema::asLinkingMappingItem));
+
+ OperationOptions options = MappingUtils.buildOperationOptions(
+ mapItems, moreAttrsToGet.toArray(new String[0]));
+
+ switch (pullTask.getPullMode()) {
+ case INCREMENTAL:
+ if (!dryRun) {
+ latestSyncTokens.put(provision.getObjectClass(), provision.getSyncToken());
+ }
+
+ connector.sync(
+ provision.getObjectClass(),
+ provision.getSyncToken(),
+ handler,
+ options);
+
+ if (!dryRun) {
+ provision.setSyncToken(latestSyncTokens.get(provision.getObjectClass()));
+ resourceDAO.save(provision.getResource());
+ }
break;
- case GROUP:
- handler = ghandler;
+ case FILTERED_RECONCILIATION:
+ connector.filteredReconciliation(
+ provision.getObjectClass(),
+ ImplementationManager.build(pullTask.getReconFilterBuilder()),
+ handler,
+ options);
break;
- case ANY_OBJECT:
+ case FULL_RECONCILIATION:
default:
- handler = buildAnyObjectHandler();
+ connector.fullReconciliation(
+ provision.getObjectClass(),
+ handler,
+ options);
+ break;
}
- handler.setProfile(profile);
- handler.setPullExecutor(this);
-
- try {
- Set<String> moreAttrsToGet = new HashSet<>();
- actions.forEach(action -> moreAttrsToGet.addAll(action.moreAttrsToGet(profile, provision)));
-
- Stream<? extends Item> mapItems = Stream.concat(
- MappingUtils.getPullItems(provision.getMapping().getItems().stream()),
- virSchemaDAO.findByProvision(provision).stream().map(VirSchema::asLinkingMappingItem));
-
- OperationOptions options = MappingUtils.buildOperationOptions(
- mapItems, moreAttrsToGet.toArray(new String[0]));
-
- switch (pullTask.getPullMode()) {
- case INCREMENTAL:
- if (!dryRun) {
- latestSyncTokens.put(provision.getObjectClass(), provision.getSyncToken());
- }
-
- connector.sync(
- provision.getObjectClass(),
- provision.getSyncToken(),
- handler,
- options);
-
- if (!dryRun) {
- provision.setSyncToken(latestSyncTokens.get(provision.getObjectClass()));
- resourceDAO.save(provision.getResource());
- }
- break;
-
- case FILTERED_RECONCILIATION:
- connector.filteredReconciliation(
- provision.getObjectClass(),
- ImplementationManager.build(pullTask.getReconFilterBuilder()),
- handler,
- options);
- break;
-
- case FULL_RECONCILIATION:
- default:
- connector.fullReconciliation(
- provision.getObjectClass(),
- handler,
- options);
- break;
- }
-
- if (provision.getUidOnCreate() != null) {
- AnyUtils anyUtils = anyUtilsFactory.getInstance(provision.getAnyType().getKind());
- profile.getResults().stream().
- filter(result -> result.getUidValue() != null && result.getKey() != null
- && result.getOperation() == ResourceOperation.CREATE
- && result.getAnyType().equals(provision.getAnyType().getKey())).
- forEach(result -> {
- anyUtils.addAttr(result.getKey(), provision.getUidOnCreate(), result.getUidValue());
- });
- }
- } catch (Throwable t) {
- throw new JobExecutionException("While pulling from connector", t);
+
+ if (provision.getUidOnCreate() != null) {
+ AnyUtils anyUtils = anyUtilsFactory.getInstance(provision.getAnyType().getKind());
+ profile.getResults().stream().
+ filter(result -> result.getUidValue() != null && result.getKey() != null
+ && result.getOperation() == ResourceOperation.CREATE
+ && result.getAnyType().equals(provision.getAnyType().getKey())).
+ forEach(result -> {
+ anyUtils.addAttr(result.getKey(), provision.getUidOnCreate(), result.getUidValue());
+ });
}
+ } catch (Throwable t) {
+ throw new JobExecutionException("While pulling from connector", t);
}
+
}
try {
setGroupOwners(ghandler);
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
index d75efc8..40834af 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
@@ -62,6 +62,7 @@ import org.apache.syncope.core.persistence.jpa.attrvalue.validation.BinaryValida
import org.apache.syncope.core.persistence.jpa.attrvalue.validation.EmailAddressValidator;
import org.apache.syncope.core.persistence.jpa.dao.DefaultPullCorrelationRule;
import org.apache.syncope.core.persistence.jpa.dao.DefaultPushCorrelationRule;
+import org.apache.syncope.core.provisioning.java.DefaultProvisionSorter;
import org.apache.syncope.core.provisioning.java.propagation.AzurePropagationActions;
import org.apache.syncope.core.provisioning.java.propagation.DBPasswordPropagationActions;
import org.apache.syncope.core.provisioning.java.propagation.GoogleAppsPropagationActions;
@@ -152,6 +153,9 @@ public class ITImplementationLookup implements ImplementationLookup {
private static final Set<Class<?>> AUDITAPPENDER_CLASSES = new HashSet<>(
List.of(TestFileAuditAppender.class, TestFileRewriteAuditAppender.class));
+ private static final Set<Class<?>> PROVISION_SORTER_CLASSES = new HashSet<>(
+ List.of(DefaultProvisionSorter.class));
+
private static final Map<String, Set<String>> CLASS_NAMES = new HashMap<String, Set<String>>() {
private static final long serialVersionUID = 3109256773218160485L;
@@ -232,6 +236,10 @@ public class ITImplementationLookup implements ImplementationLookup {
classNames = ITImplementationLookup.AUDITAPPENDER_CLASSES.stream().
map(Class::getName).collect(Collectors.toSet());
put(IdRepoImplementationType.AUDIT_APPENDER, classNames);
+
+ classNames = ITImplementationLookup.PROVISION_SORTER_CLASSES.stream().
+ map(Class::getName).collect(Collectors.toSet());
+ put(IdMImplementationType.PROVISION_SORTER, classNames);
}
};
diff --git a/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/view/ResourceExplorerTopComponent.java b/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/view/ResourceExplorerTopComponent.java
index 3a25faf..9e4096d 100644
--- a/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/view/ResourceExplorerTopComponent.java
+++ b/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/view/ResourceExplorerTopComponent.java
@@ -183,7 +183,7 @@ public final class ResourceExplorerTopComponent extends TopComponent {
getLastSelectedPathComponent();
DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) selectedNode.getParent();
String parentNodeName = Optional.ofNullable(parentNode)
- .map(node -> String.valueOf(node.getUserObject())).orElse(null);
+ .map(node -> String.valueOf(node.getUserObject())).orElse(null);
if (selectedNode.isLeaf() && StringUtils.isNotBlank(parentNodeName)) {
String leafNodeName = (String) selectedNode.getUserObject();
DefaultMutableTreeNode grandParentNode = (DefaultMutableTreeNode) parentNode.getParent();
@@ -298,7 +298,7 @@ public final class ResourceExplorerTopComponent extends TopComponent {
private void addMailTemplates() {
List<MailTemplateTO> mailTemplateList = mailTemplateManagerService.list();
mailTemplateList
- .forEach(mailTemplate -> this.mailTemplates.add(new DefaultMutableTreeNode(mailTemplate.getKey())));
+ .forEach(mailTemplate -> this.mailTemplates.add(new DefaultMutableTreeNode(mailTemplate.getKey())));
treeModel.reload();
}
@@ -446,6 +446,10 @@ public final class ResourceExplorerTopComponent extends TopComponent {
templateClassName = "MyRecipientsProvider";
break;
+ case IdMImplementationType.PROVISION_SORTER:
+ templateClassName = "MyProvisionSorter";
+ break;
+
default:
}
newNode.setBody(IOUtils.toString(getClass().getResourceAsStream(
@@ -719,8 +723,6 @@ public final class ResourceExplorerTopComponent extends TopComponent {
componentClosed();
componentOpened();
}
-
};
}
-
}