diff --git a/build-system/pom.xml b/build-system/pom.xml index 90db6a74dd3..3ea5ce2a29a 100644 --- a/build-system/pom.xml +++ b/build-system/pom.xml @@ -49,7 +49,7 @@ 2.6 3.7 1.2 - 3.2.1 + 3.2.4 3.2.0 2.2.0 2.4.7 @@ -63,7 +63,8 @@ 1.0.1 1.7.25 1.2.3 - 1.5.8.e1 + 1.5.8.e1 4.3.14.RELEASE 4.2.4.RELEASE 3.5.0 diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/password/PasswordPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/password/PasswordPanel.java index 2b96c1f0160..139ebd5a0d3 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/password/PasswordPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/password/PasswordPanel.java @@ -256,7 +256,7 @@ protected void onUpdate(AjaxRequestTarget target) { } } - private class PasswordModel implements IModel { + private static class PasswordModel implements IModel { IModel psModel; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebModelServiceUtils.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebModelServiceUtils.java index 9dd2b074312..b25e4e1106c 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebModelServiceUtils.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebModelServiceUtils.java @@ -713,8 +713,7 @@ public static void addIncludeOptionsForExportOrView(Collection keys = map.keySet().iterator(); + Iterator> keys = map.entrySet().iterator(); while (keys.hasNext()) { - String key = keys.next(); - sb.append(key).append(":"); - sb.append('\'').append(map.get(key)).append('\''); + final Map.Entry key = keys.next(); + sb.append(key.getKey()).append(":"); + sb.append('\'').append(key.getValue()).append('\''); if (keys.hasNext()) { sb.append(",\n"); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AbstractRoleAssignmentPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AbstractRoleAssignmentPanel.java index 154bc354350..7b3ca17a581 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AbstractRoleAssignmentPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AbstractRoleAssignmentPanel.java @@ -51,6 +51,7 @@ import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.prism.query.builder.QueryBuilder; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; +import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.web.component.AjaxButton; import com.evolveum.midpoint.web.component.form.Form; import com.evolveum.midpoint.web.component.input.DropDownChoicePanel; @@ -206,7 +207,6 @@ protected void addSelectedAssignmentsPerformed(AjaxReques constructionType.setResourceRef(ref); constructionType.setKind(kind); constructionType.setIntent(intent); - initAssociationContainer(constructionType); assignmentType.setConstruction(constructionType); } else { assignmentType.setTargetRef(ref); @@ -218,9 +218,6 @@ protected void addSelectedAssignmentsPerformed(AjaxReques reloadSavePreviewButtons(target); } - protected void initAssociationContainer(ConstructionType constructionType){ - } - protected List, String>> initColumns() { List, String>> columns = new ArrayList<>(); @@ -231,6 +228,25 @@ public void populateItem(Item, String>(createStringResource("AssignmentType.tenant")){ + private static final long serialVersionUID = 1L; + + @Override + public void populateItem(Item>> item, String componentId, + final IModel> rowModel) { + item.add(new Label(componentId, getTenantLabelModel(rowModel.getObject()))); + } + }); + columns.add(new AbstractColumn, String>(createStringResource("AssignmentType.orgReferenceShorten")){ + private static final long serialVersionUID = 1L; + + @Override + public void populateItem(Item>> item, String componentId, + final IModel> rowModel) { + item.add(new Label(componentId, getOrgRefLabelModel(rowModel.getObject()))); + } + }); + return columns; } @@ -308,30 +324,6 @@ protected AbstractAssignmentDetailsPanel createDetailsPanel(String idAssignmentD return new AbstractRoleAssignmentDetailsPanel(ID_ASSIGNMENT_DETAILS, form, model); } - @Override - protected List, String>> initBasicColumns() { - List, String>> columns = super.initBasicColumns(); - columns.add(new AbstractColumn, String>(createStringResource("AssignmentType.tenant")){ - private static final long serialVersionUID = 1L; - - @Override - public void populateItem(Item>> item, String componentId, - final IModel> rowModel) { - item.add(new Label(componentId, getTenantLabelModel(rowModel.getObject()))); - } - }); - columns.add(new AbstractColumn, String>(createStringResource("AssignmentType.orgReferenceShorten")){ - private static final long serialVersionUID = 1L; - - @Override - public void populateItem(Item>> item, String componentId, - final IModel> rowModel) { - item.add(new Label(componentId, getOrgRefLabelModel(rowModel.getObject()))); - } - }); - return columns; - } - private IModel getTenantLabelModel(ContainerValueWrapper assignmentContainer){ if (assignmentContainer == null || assignmentContainer.getContainerValue() == null){ return Model.of(""); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/ApplicablePolicyGroupPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/ApplicablePolicyGroupPanel.java index e1f4cb57d8f..7f6a21487dd 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/ApplicablePolicyGroupPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/ApplicablePolicyGroupPanel.java @@ -27,6 +27,7 @@ import com.evolveum.midpoint.prism.query.builder.QueryBuilder; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; +import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.component.data.column.IsolatedCheckBoxPanel; @@ -171,13 +172,15 @@ private void onPolicyAddedOrRemoved(PrismObject assignmentTarg assignmentsModel.getObject().getValues().remove(assignmentToRemove); } else { if (added){ + //TODO: not sure if this is correct way of creating new value.. this value is added directly to the origin object... what about deltas?? PrismContainerValue newAssignment = assignmentsModel.getObject().getItem().createNewValue(); ObjectReferenceType ref = ObjectTypeUtil.createObjectRef(assignmentTargetObject); AssignmentType assignmentType = newAssignment.asContainerable(); assignmentType.setTargetRef(ref); + Task task = getPageBase().createSimpleTask("Creating new applicable policy"); ContainerWrapperFactory factory = new ContainerWrapperFactory(getPageBase()); ContainerValueWrapper valueWrapper = factory.createContainerValueWrapper(assignmentsModel.getObject(), newAssignment, - assignmentsModel.getObject().getObjectStatus(), ValueStatus.ADDED, assignmentsModel.getObject().getPath()); + assignmentsModel.getObject().getObjectStatus(), ValueStatus.ADDED, assignmentsModel.getObject().getPath(), task); valueWrapper.setShowEmpty(true, false); assignmentsModel.getObject().getValues().add(valueWrapper); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AssignmentPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AssignmentPanel.java index 68ca698b1e4..991f80fc8cc 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AssignmentPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AssignmentPanel.java @@ -50,6 +50,7 @@ import com.evolveum.midpoint.prism.query.ObjectPaging; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.security.api.AuthorizationConstants; +import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.web.component.AjaxButton; import com.evolveum.midpoint.web.component.AjaxIconButton; import com.evolveum.midpoint.web.component.data.BoxedTablePanel; @@ -224,7 +225,7 @@ protected AssignmentsTabStorage getAssignmentsStorage() { protected abstract ObjectQuery createObjectQuery(); - protected List, String>> initBasicColumns() { + private List, String>> initBasicColumns() { List, String>> columns = new ArrayList<>(); columns.add(new CheckBoxHeaderColumn<>()); @@ -459,8 +460,9 @@ protected void deleteAssignmentPerformed(AjaxRequestTarget target, List createNewAssignmentContainerValueWrapper(PrismContainerValue newAssignment) { ContainerWrapperFactory factory = new ContainerWrapperFactory(getPageBase()); + Task task = getPageBase().createSimpleTask("Creating new assignment"); ContainerValueWrapper valueWrapper = factory.createContainerValueWrapper(getModelObject(), newAssignment, - getModelObject().getObjectStatus(), ValueStatus.ADDED, getModelObject().getPath()); + getModelObject().getObjectStatus(), ValueStatus.ADDED, getModelObject().getPath(), task); valueWrapper.setShowEmpty(true, false); getModelObject().getValues().add(valueWrapper); return valueWrapper; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/ConstructionAssociationPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/ConstructionAssociationPanel.java index 0128cb7d22d..e2c10c755ab 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/ConstructionAssociationPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/ConstructionAssociationPanel.java @@ -237,11 +237,13 @@ public List load() { PrismContainerValue associationValue = ((ContainerValueWrapper) associationValueWrapper).getContainerValue(); ResourceObjectAssociationType assoc = (ResourceObjectAssociationType) associationValue.asContainerable(); if (assoc == null || assoc.getOutbound() == null || assoc.getOutbound().getExpression() == null - || ExpressionUtil.getShadowRefValue(assoc.getOutbound().getExpression()) == null) { + || (ExpressionUtil.getShadowRefValue(assoc.getOutbound().getExpression()) == null + && !ValueStatus.ADDED.equals(((ContainerValueWrapper) associationValueWrapper).getStatus()))) { return; } QName assocRef = ItemPathUtil.getOnlySegmentQName(assoc.getRef()); - if (defName != null && defName.equals(assocRef)) { + if ((defName != null && defName.equals(assocRef)) + || (assocRef == null && ValueStatus.ADDED.equals(((ContainerValueWrapper) associationValueWrapper).getStatus()))) { shadowsList.add(ExpressionUtil.getShadowRefValue(assoc.getOutbound().getExpression())); } }); @@ -279,6 +281,7 @@ private List getAssociationsShadowRefs(boolean compareName, private void addNewShadowRefValuePerformed(AjaxRequestTarget target, RefinedAssociationDefinition def){ ObjectFilter filter = WebComponentUtil.createAssociationShadowRefFilter(def, getPageBase().getPrismContext(), resourceModel.getObject().getOid()); + Task task = getPageBase().createAnonymousTask("Adding new shadow"); ObjectBrowserPanel objectBrowserPanel = new ObjectBrowserPanel( getPageBase().getMainPopupBodyId(), ShadowType.class, Arrays.asList(ShadowType.COMPLEX_TYPE), false, getPageBase(), @@ -302,7 +305,7 @@ protected void onSelectPerformed(AjaxRequestTarget target, ShadowType object) { ContainerWrapperFactory factory = new ContainerWrapperFactory(getPageBase()); ContainerValueWrapper valueWrapper = factory.createContainerValueWrapper(associationWrapper, newAssociation, - associationWrapper.getObjectStatus(), ValueStatus.ADDED, associationWrapper.getPath()); + associationWrapper.getObjectStatus(), ValueStatus.ADDED, associationWrapper.getPath(), task); // valueWrapper.setShowEmpty(true, false); associationWrapper.getValues().add(valueWrapper); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/InducedEntitlementsPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/InducedEntitlementsPanel.java index a30b6f77094..89c9d84718d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/InducedEntitlementsPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/InducedEntitlementsPanel.java @@ -1,19 +1,33 @@ package com.evolveum.midpoint.web.component.assignment; +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.prism.query.AndFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ObjectPaging; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.prism.query.builder.QueryBuilder; import com.evolveum.midpoint.schema.constants.ObjectTypes; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.component.form.Form; import com.evolveum.midpoint.web.component.prism.ContainerValueWrapper; import com.evolveum.midpoint.web.component.prism.ContainerWrapper; +import com.evolveum.midpoint.web.component.prism.ValueStatus; import com.evolveum.midpoint.web.session.AssignmentsTabStorage; import com.evolveum.midpoint.web.session.UserProfileStorage; +import com.evolveum.midpoint.web.util.ExpressionUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import org.apache.commons.lang.StringUtils; +import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator; +import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn; +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.repeater.Item; import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import javax.jws.WebParam; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -24,6 +38,9 @@ public class InducedEntitlementsPanel extends InducementsPanel{ private static final long serialVersionUID = 1L; + private static final Trace LOGGER = TraceManager.getTrace(InducedEntitlementsPanel.class); + private static final String DOT_CLASS = InducedEntitlementsPanel.class.getName() + "."; + private static final String OPERATION_LOAD_SHADOW_DISPLAY_NAME = DOT_CLASS + "loadShadowDisplayName"; public InducedEntitlementsPanel(String id, IModel> inducementContainerWrapperModel){ super(id, inducementContainerWrapperModel); @@ -49,16 +66,46 @@ private AssignmentsTabStorage getInducedEntitlementsTabStorage(){ return getParentPage().getSessionStorage().getInducedEntitlementsTabStorage(); } + @Override + protected List, String>> initColumns() { + List, String>> columns = new ArrayList<>(); + columns.add(new AbstractColumn, String>(createStringResource("ConstructionType.kind")){ + private static final long serialVersionUID = 1L; + + @Override + public void populateItem(Item>> item, String componentId, + final IModel> rowModel) { + item.add(new Label(componentId, getKindLabelModel(rowModel.getObject()))); + } + }); + columns.add(new AbstractColumn, String>(createStringResource("ConstructionType.intent")){ + private static final long serialVersionUID = 1L; + + @Override + public void populateItem(Item>> item, String componentId, + final IModel> rowModel) { + item.add(new Label(componentId, getIntentLabelModel(rowModel.getObject()))); + } + }); + columns.add(new AbstractColumn, String>(createStringResource("ConstructionType.association")){ + private static final long serialVersionUID = 1L; + + @Override + public void populateItem(Item>> item, String componentId, + final IModel> rowModel) { + item.add(new Label(componentId, getAssociationLabelModel(rowModel.getObject()))); + } + }); + + return columns; + } + @Override protected ObjectQuery createObjectQuery() { ObjectQuery query = super.createObjectQuery(); ObjectFilter filter = query.getFilter(); ObjectQuery entitlementsQuery = QueryBuilder.queryFor(AssignmentType.class, getParentPage().getPrismContext()) - .block() - .not() - .item(AssignmentType.F_CONSTRUCTION, ConstructionType.F_ASSOCIATION, ResourceObjectAssociationType.F_OUTBOUND, MappingType.F_EXPRESSION) - .isNull() - .endBlock() + .exists(AssignmentType.F_CONSTRUCTION) .build(); if (filter != null){ query.setFilter(AndFilter.createAnd(filter, entitlementsQuery.getFilter())); @@ -79,11 +126,6 @@ protected Class getDefaultNewAssignmentFocusType(){ } @Override - - protected void initAssociationContainer(ConstructionType constructionType){ - constructionType.beginAssociation().beginOutbound().beginExpression(); - } - protected boolean isRelationVisible() { return false; } @@ -91,4 +133,92 @@ protected boolean isRelationVisible() { protected List getObjectTypesList(){ return Arrays.asList(ObjectTypes.RESOURCE); } + + private IModel getKindLabelModel(ContainerValueWrapper assignmentWrapper){ + if (assignmentWrapper == null){ + return Model.of(""); + } + AssignmentType assignment = assignmentWrapper.getContainerValue().asContainerable(); + ConstructionType construction = assignment.getConstruction(); + if (construction == null || construction.getKind() == null){ + return Model.of(""); + } + return WebComponentUtil.createLocalizedModelForEnum(construction.getKind(), InducedEntitlementsPanel.this); + + } + + private IModel getIntentLabelModel(ContainerValueWrapper assignmentWrapper){ + if (assignmentWrapper == null){ + return Model.of(""); + } + AssignmentType assignment = assignmentWrapper.getContainerValue().asContainerable(); + ConstructionType construction = assignment.getConstruction(); + if (construction == null || construction.getIntent() == null){ + return Model.of(""); + } + return Model.of(construction.getIntent()); + + } + + private IModel getAssociationLabelModel(ContainerValueWrapper assignmentWrapper){ + if (assignmentWrapper == null){ + return Model.of(""); + } + AssignmentType assignment = assignmentWrapper.getContainerValue().asContainerable(); + ConstructionType construction = assignment.getConstruction(); + if (construction == null || construction.getAssociation() == null){ + return Model.of(""); + } + StringBuilder sb = new StringBuilder(); + for (ResourceObjectAssociationType association : construction.getAssociation()){ + if (association.getOutbound() == null || association.getOutbound().getExpression() == null){ + continue; + } + ObjectReferenceType shadowRefValue = ExpressionUtil.getShadowRefValue(association.getOutbound().getExpression()); + if (shadowRefValue == null || StringUtils.isEmpty(shadowRefValue.getOid())){ + continue; + } + String shadowDisplayName = WebComponentUtil.getDisplayNameOrName(shadowRefValue, getPageBase(), OPERATION_LOAD_SHADOW_DISPLAY_NAME); + if (sb.length() == 0){ + sb.append(createStringResource("ExpressionValuePanel.shadowRefValueTitle").getString() + ":"); + } + if (StringUtils.isNotEmpty(shadowDisplayName)){ + sb.append("\n"); + sb.append(shadowDisplayName); + } + } + return Model.of(sb.toString()); + + } + + @Override + protected List> postSearch(List> assignments) { + List> filteredAssignments = new ArrayList<>(); + assignments.forEach(assignmentWrapper -> { + AssignmentType assignment = assignmentWrapper.getContainerValue().asContainerable(); + if (assignment.getConstruction() != null && assignment.getConstruction().getAssociation() != null) { + List associations = assignment.getConstruction().getAssociation(); + if (associations.size() == 0 && ValueStatus.ADDED.equals(assignmentWrapper.getStatus())){ + filteredAssignments.add(assignmentWrapper); + return; + } + associations.forEach(association -> { + if (!filteredAssignments.contains(assignmentWrapper)) { + if (association.getOutbound() == null && ValueStatus.ADDED.equals(assignmentWrapper.getStatus())) { + filteredAssignments.add(assignmentWrapper); + return; + } + if (association.getOutbound() != null && association.getOutbound().getExpression() != null) { + ObjectReferenceType shadowRef = ExpressionUtil.getShadowRefValue(association.getOutbound().getExpression()); + if ((shadowRef != null || ValueStatus.ADDED.equals(assignmentWrapper.getStatus()))) { + filteredAssignments.add(assignmentWrapper); + return; + } + } + } + }); + } + }); + return filteredAssignments; + } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/PolicyRulesPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/PolicyRulesPanel.java index 0da6c489ad4..aa103d0704f 100755 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/PolicyRulesPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/PolicyRulesPanel.java @@ -141,6 +141,7 @@ protected void newAssignmentClickPerformed(AjaxRequestTarget target) { newAssignment.asContainerable().setPolicyRule(new PolicyRuleType()); ContainerValueWrapper newAssignmentWrapper = createNewAssignmentContainerValueWrapper(newAssignment); newAssignmentWrapper.setShowEmpty(true, false); + newAssignmentWrapper.computeStripes(); assignmentDetailsPerformed(target, Arrays.asList(newAssignmentWrapper)); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/SelectableDataTable.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/SelectableDataTable.java index 1bcfe9e89a3..c7779144282 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/SelectableDataTable.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/SelectableDataTable.java @@ -60,7 +60,7 @@ public SelectableRowItem(String id, int index, IModel model) { @Override protected Item> newCellItem(String id, int index, IModel> model) { Item item = super.newCellItem(id, index, model); - item.add(new AttributeModifier("style", "max-width: 250px; word-wrap: break-word;")); + item.add(new AttributeModifier("style", "word-wrap: break-word;")); return item; } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerValueWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerValueWrapper.java index 067a1c22aa1..7bb8e395336 100755 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerValueWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerValueWrapper.java @@ -155,15 +155,17 @@ public void computeStripes() { } int visibleProperties = 0; - for (ItemWrapper item : properties) { + for (ItemWrapper item : properties) { if (item.isVisible()) { visibleProperties++; } + if (visibleProperties % 2 == 0) { item.setStripe(true); } else { item.setStripe(false); } + } } @@ -284,9 +286,40 @@ public void sort() { if (isSorted()) { collator.setStrength(Collator.SECONDARY); // e.g. "a" should be different from "รก" collator.setDecomposition(Collator.FULL_DECOMPOSITION); // slower but more precise + +// List containerWrappers = new ArrayList<>(); +// List propertyOrReferenceWrapper = new ArrayList<>(); +// for(ItemWrapper w : properties) { +// if (w instanceof ContainerWrapper) { +// containerWrappers.add(w); +// continue; +// } +// +// if (PropertyOrReferenceWrapper.class.isAssignableFrom(w.getClass())) { +// propertyOrReferenceWrapper.add(w); +// } +// } + Collections.sort(properties, new Comparator() { @Override public int compare(ItemWrapper pw1, ItemWrapper pw2) { + + if (pw1 instanceof ContainerWrapper) { + ((ContainerWrapper) pw1).sort(); + } + + if (pw2 instanceof ContainerWrapper) { + ((ContainerWrapper) pw2).sort(); + } + + if (PropertyOrReferenceWrapper.class.isAssignableFrom(pw1.getClass()) && pw2 instanceof ContainerWrapper) { + return -1; + } + + if (PropertyOrReferenceWrapper.class.isAssignableFrom(pw2.getClass()) && pw1 instanceof ContainerWrapper) { + return 1; + } +// return compareByDisplayNames(pw1, pw2, collator); } }); @@ -294,6 +327,23 @@ public int compare(ItemWrapper pw1, ItemWrapper pw2) { Collections.sort(properties, new Comparator() { @Override public int compare(ItemWrapper pw1, ItemWrapper pw2) { + + if (pw1 instanceof ContainerWrapper) { + ((ContainerWrapper) pw1).sort(); + } + + if (pw2 instanceof ContainerWrapper) { + ((ContainerWrapper) pw2).sort(); + } + + if (PropertyOrReferenceWrapper.class.isAssignableFrom(pw1.getClass()) && pw2 instanceof ContainerWrapper) { + return -1; + } + + if (PropertyOrReferenceWrapper.class.isAssignableFrom(pw2.getClass()) && pw1 instanceof ContainerWrapper) { + return 1; + } + ItemDefinition id1 = pw1.getItemDefinition(); ItemDefinition id2 = pw2.getItemDefinition(); @@ -307,6 +357,7 @@ public int compare(ItemWrapper pw1, ItemWrapper pw2) { } }); } + } private int compareByDisplayNames(ItemWrapper pw1, ItemWrapper pw2, Collator collator) { @@ -548,25 +599,7 @@ private void addItemDelta(PropertyOrReferenceWrapper itemWrapper, ItemDelta pDel } } - public void addNewChildContainerValue(QName path, PageBase pageBase){ - ContainerWrapper childContainerWrapper = getContainer().findContainerWrapper(new ItemPath(getPath(), path)); - if (childContainerWrapper == null){ - return; - } - boolean isSingleValue = childContainerWrapper.getItemDefinition().isSingleValue(); - if (isSingleValue){ - return; - } - PrismContainerValue newContainerValue = childContainerWrapper.getItem().createNewValue(); - ContainerWrapperFactory factory = new ContainerWrapperFactory(pageBase); - ContainerValueWrapper newValueWrapper = factory.createContainerValueWrapper(childContainerWrapper, - newContainerValue, objectStatus, - ValueStatus.ADDED, new ItemPath(path)); - newValueWrapper.setShowEmpty(true, false); - childContainerWrapper.getValues().add(newValueWrapper); - - } - + private Item createItem(PropertyOrReferenceWrapper itemWrapper, ItemDefinition propertyDef) { List prismValues = new ArrayList<>(); for (Object vWrapper : itemWrapper.getValues()) { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java index e281bcc6cc2..f1dd4a30a2b 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapper.java @@ -376,7 +376,9 @@ public boolean isStripe() { @Override public void setStripe(boolean isStripe) { - // Does not make much sense, but it is given by the interface + for (ContainerValueWrapper value : values) { + value.computeStripes(); + } } public PrismContainer createContainerAddDelta() throws SchemaException { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapperFactory.java index 7aba8036740..50b3fb884d2 100755 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapperFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ContainerWrapperFactory.java @@ -32,6 +32,7 @@ import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.exception.TunnelException; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -85,13 +86,14 @@ public ContainerWrapper createContainerWrapper( PrismContainer container, ContainerStatus objectStatus, ContainerStatus status, - ItemPath path) { + ItemPath path, + Task task) { result = new OperationResult(CREATE_PROPERTIES); ContainerWrapper cWrapper = new ContainerWrapper(container, objectStatus, status, path); - List> containerValues = createContainerValues(cWrapper, path); + List> containerValues = createContainerValues(cWrapper, path, task); cWrapper.setProperties(containerValues); cWrapper.computeStripes(); @@ -217,13 +219,13 @@ private boolean isEmpty(ValueWrapper shadowAssociationRef) { } - public ContainerWrapper createContainerWrapper(PrismContainer container, ContainerStatus objectStatus, ContainerStatus status, ItemPath path, boolean readonly) { + public ContainerWrapper createContainerWrapper(PrismContainer container, ContainerStatus objectStatus, ContainerStatus status, ItemPath path, boolean readonly, Task task) { result = new OperationResult(CREATE_PROPERTIES); ContainerWrapper cWrapper = new ContainerWrapper<>(container, objectStatus, status, path, readonly); - List> containerValues = createContainerValues(cWrapper, path); + List> containerValues = createContainerValues(cWrapper, path, task); cWrapper.setProperties(containerValues); cWrapper.computeStripes(); @@ -231,20 +233,20 @@ public ContainerWrapper createContainerWrapper(Pris return cWrapper; } - private List> createContainerValues(ContainerWrapper cWrapper, ItemPath path) { + private List> createContainerValues(ContainerWrapper cWrapper, ItemPath path, Task task) { List> containerValueWrappers = new ArrayList<>(); PrismContainer container = cWrapper.getItem(); if (container.getValues().isEmpty() && container.isSingleValue()) { PrismContainerValue pcv = container.createNewValue(); - ContainerValueWrapper containerValueWrapper = createContainerValueWrapper(cWrapper, pcv, cWrapper.getObjectStatus(), ValueStatus.ADDED, cWrapper.getPath()); + ContainerValueWrapper containerValueWrapper = createContainerValueWrapper(cWrapper, pcv, cWrapper.getObjectStatus(), ValueStatus.ADDED, cWrapper.getPath(), task); containerValueWrappers.add(containerValueWrapper); return containerValueWrappers; } container.getValues().forEach(pcv -> { - ContainerValueWrapper containerValueWrapper = createContainerValueWrapper(cWrapper, pcv, cWrapper.getObjectStatus(), cWrapper.getStatus() == ContainerStatus.ADDING ? ValueStatus.ADDED : ValueStatus.NOT_CHANGED, pcv.getPath()); + ContainerValueWrapper containerValueWrapper = createContainerValueWrapper(cWrapper, pcv, cWrapper.getObjectStatus(), cWrapper.getStatus() == ContainerStatus.ADDING ? ValueStatus.ADDED : ValueStatus.NOT_CHANGED, pcv.getPath(), task); containerValueWrappers.add(containerValueWrapper); }); @@ -252,10 +254,10 @@ private List> createContainer return containerValueWrappers; } - public ContainerValueWrapper createContainerValueWrapper(ContainerWrapper cWrapper, PrismContainerValue value, ContainerStatus objectStatus, ValueStatus status, ItemPath path){ + public ContainerValueWrapper createContainerValueWrapper(ContainerWrapper cWrapper, PrismContainerValue value, ContainerStatus objectStatus, ValueStatus status, ItemPath path, Task task){ ContainerValueWrapper containerValueWrapper = new ContainerValueWrapper(cWrapper, value, objectStatus, status, path); - List properties = createProperties(containerValueWrapper, false); + List properties = createProperties(containerValueWrapper, false, task); containerValueWrapper.setProperties(properties); ReferenceWrapper shadowRefWrapper = (ReferenceWrapper) containerValueWrapper.findPropertyWrapper(ShadowAssociationType.F_SHADOW_REF); @@ -266,7 +268,7 @@ public ContainerValueWrapper createContainerValueWr return containerValueWrapper; } - public List createProperties(ContainerValueWrapper cWrapper, boolean onlyEmpty) { + public List createProperties(ContainerValueWrapper cWrapper, boolean onlyEmpty, Task task) { result = new OperationResult(CREATE_PROPERTIES); @@ -291,14 +293,20 @@ public List createP return; } - if (itemDef.isExperimental() && !WebModelServiceUtils.isEnableExperimentalFeature(modelServiceLocator)) { + if (itemDef.isExperimental() && !WebModelServiceUtils.isEnableExperimentalFeature(task, modelServiceLocator)) { LOGGER.trace("Skipping creating wrapper for {} because it is experimental a experimental features are not enabled.", itemDef.getName()); return; } LOGGER.trace("Creating wrapper for {}", itemDef); + try { createPropertyOrReferenceWrapper(itemDef, cWrapper, propertyOrReferenceWrappers, onlyEmpty, cWrapper.getPath()); - createContainerWrapper(itemDef, cWrapper, containerWrappers, onlyEmpty); + createContainerWrapper(itemDef, cWrapper, containerWrappers, onlyEmpty, task); + } catch (Exception e) { + LoggingUtils.logUnexpectedException(LOGGER, "something strange happenned: " + e.getMessage(), e); + System.out.println(e.getMessage()); + throw new TunnelException(e); + } }); @@ -330,7 +338,7 @@ private void createPropertyOrReferenceWrapper(ItemDefi private void createContainerWrapper(ItemDefinition itemDef, ContainerValueWrapper cWrapper, - List> properties, boolean onlyEmpty){ + List> properties, boolean onlyEmpty, Task task){ if (itemDef instanceof PrismContainerDefinition) { @@ -367,7 +375,7 @@ private void createContainerWrapper(ItemDefinition ite // } // // } else { - subContainerWrapper = createContainerWrapper((PrismContainerDefinition) itemDef, cWrapper, onlyEmpty); + subContainerWrapper = createContainerWrapper((PrismContainerDefinition) itemDef, cWrapper, onlyEmpty, task); // } if (subContainerWrapper == null) { @@ -456,7 +464,7 @@ private ReferenceWrapper createReferenceWrapper(PrismR } private ContainerWrapper createContainerWrapper(PrismContainerDefinition def, - ContainerValueWrapper cWrapper, boolean onlyEmpty) { + ContainerValueWrapper cWrapper, boolean onlyEmpty, Task task) { PrismContainerValue containerValue = cWrapper.getContainerValue(); @@ -487,9 +495,9 @@ private ContainerWrapper createContainerWrapper(Pri return null; } return createContainerWrapper(newContainer, cWrapper.getObjectStatus(), ContainerStatus.ADDING, - cWrapper.getPath().append(new ItemPath(newContainer.getElementName()))); + cWrapper.getPath().append(new ItemPath(newContainer.getElementName())), task); } - return createContainerWrapper(container, cWrapper.getObjectStatus(), cWrapper.getStatus() == ValueStatus.ADDED ? ContainerStatus.ADDING: ContainerStatus.MODIFYING, container.getPath()); + return createContainerWrapper(container, cWrapper.getObjectStatus(), cWrapper.getStatus() == ValueStatus.ADDED ? ContainerStatus.ADDING: ContainerStatus.MODIFYING, container.getPath(), task); } private boolean isItemReadOnly(ItemDefinition def, ContainerValueWrapper cWrapper) { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ItemWrapperComparator.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ItemWrapperComparator.java index 5e2b9305278..14ce8944465 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ItemWrapperComparator.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ItemWrapperComparator.java @@ -42,10 +42,12 @@ public int compare(ItemWrapper p1, ItemWrapper p2) { } if (def1 instanceof PrismContainerDefinition) { + ((ContainerWrapper) p1).sort(); return 1; } - if (def1 instanceof PrismContainerDefinition) { + if (def2 instanceof PrismContainerDefinition) { + ((ContainerWrapper) p2).sort(); return 1; } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ObjectWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ObjectWrapperFactory.java index 3f7cd0c768a..9b737d08b6f 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ObjectWrapperFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ObjectWrapperFactory.java @@ -133,7 +133,7 @@ public ObjectWrapper createObjectWrapper(String displa } return createObjectWrapper(displayName, description, object, objectDefinitionForEditing, - objectClassDefinitionForEditing, status, result); + objectClassDefinitionForEditing, status, task, result); } catch (SchemaException | ConfigurationException | ObjectNotFoundException | ExpressionEvaluationException | CommunicationException | SecurityViolationException ex) { throw new SystemException(ex); } @@ -141,15 +141,15 @@ public ObjectWrapper createObjectWrapper(String displa public ObjectWrapper createObjectWrapper(String displayName, String description, PrismObject object, PrismObjectDefinition objectDefinitionForEditing, - RefinedObjectClassDefinition objectClassDefinitionForEditing, ContainerStatus status) throws SchemaException { + RefinedObjectClassDefinition objectClassDefinitionForEditing, ContainerStatus status, Task task) throws SchemaException { return createObjectWrapper(displayName, description, object, objectDefinitionForEditing, - objectClassDefinitionForEditing, status, null); + objectClassDefinitionForEditing, status, task, null); } private ObjectWrapper createObjectWrapper(String displayName, String description, PrismObject object, PrismObjectDefinition objectDefinitionForEditing, RefinedObjectClassDefinition objectClassDefinitionForEditing, ContainerStatus status, - OperationResult result) throws SchemaException { + Task task, OperationResult result) throws SchemaException { if (result == null) { this.result = new OperationResult(CREATE_OBJECT_WRAPPER); @@ -161,7 +161,7 @@ private ObjectWrapper createObjectWrapper(String displ status); List> containerWrappers = createContainerWrappers(objectWrapper, object, - objectDefinitionForEditing, status, this.result); + objectDefinitionForEditing, status, task, this.result); objectWrapper.setContainers(containerWrappers); this.result.computeStatusIfUnknown(); @@ -176,21 +176,21 @@ private ObjectWrapper createObjectWrapper(String displ } private List> createContainerWrappers(ObjectWrapper oWrapper, - PrismObject object, PrismObjectDefinition objectDefinitionForEditing, ContainerStatus cStatus, OperationResult pResult) throws SchemaException { + PrismObject object, PrismObjectDefinition objectDefinitionForEditing, ContainerStatus cStatus, Task task, OperationResult pResult) throws SchemaException { OperationResult result = pResult.createSubresult(CREATE_CONTAINERS); List> containerWrappers = new ArrayList<>(); ContainerWrapperFactory cwf = new ContainerWrapperFactory(modelServiceLocator); try { - ContainerWrapper mainContainerWrapper = cwf.createContainerWrapper(object, oWrapper.getStatus(), cStatus, ItemPath.EMPTY_PATH); + ContainerWrapper mainContainerWrapper = cwf.createContainerWrapper(object, oWrapper.getStatus(), cStatus, ItemPath.EMPTY_PATH, task); mainContainerWrapper.setDisplayName("prismContainer.mainPanelDisplayName"); result.addSubresult(cwf.getResult()); containerWrappers.add(mainContainerWrapper); - addContainerWrappers(containerWrappers, oWrapper, object, null, result); + addContainerWrappers(containerWrappers, oWrapper, object, null, task, result); } catch (SchemaException | RuntimeException e) { - LoggingUtils.logUnexpectedException(LOGGER, "Error occurred during container wrapping", e); + LoggingUtils.logUnexpectedException(LOGGER, "Error occurred during container wrapping" + e.getMessage(), e); result.recordFatalError("Error occurred during container wrapping, reason: " + e.getMessage(), e); throw e; } @@ -205,7 +205,7 @@ private List> c private void addContainerWrappers( List> containerWrappers, ObjectWrapper oWrapper, - PrismContainer parentContainer, ItemPath path, OperationResult result) throws SchemaException { + PrismContainer parentContainer, ItemPath path, Task task, OperationResult result) throws SchemaException { PrismContainerDefinition parentContainerDefinition = parentContainer.getDefinition(); @@ -222,7 +222,7 @@ private void addContainerWrapper continue; } - if (def.isExperimental() && !WebModelServiceUtils.isEnableExperimentalFeature(modelServiceLocator)) { + if (def.isExperimental() && !WebModelServiceUtils.isEnableExperimentalFeature(task, modelServiceLocator)) { LOGGER.trace("Skipping creating wrapper for container {} because it is experimental a experimental features are not enabled.", def.getName()); continue; } @@ -237,7 +237,7 @@ private void addContainerWrapper PrismContainer prismContainer = parentContainer.findContainer(def.getName()); - ContainerWrapper container = createContainerWrapper(oWrapper.getObject(), oWrapper.getStatus(), prismContainer, containerDef, cwf, newPath); + ContainerWrapper container = createContainerWrapper(oWrapper.getObject(), oWrapper.getStatus(), prismContainer, containerDef, cwf, newPath, task); result.addSubresult(cwf.getResult()); if (container != null) { containerWrappers.add(container); @@ -246,7 +246,8 @@ private void addContainerWrapper } } - private ContainerWrapper createContainerWrapper(PrismObject object, ContainerStatus objectStatus, PrismContainer prismContainer, PrismContainerDefinition containerDef, ContainerWrapperFactory cwf, ItemPath newPath) throws SchemaException{ + private ContainerWrapper createContainerWrapper(PrismObject object, ContainerStatus objectStatus, PrismContainer prismContainer, + PrismContainerDefinition containerDef, ContainerWrapperFactory cwf, ItemPath newPath, Task task) throws SchemaException{ if (ShadowAssociationType.COMPLEX_TYPE.equals(containerDef.getTypeName())) { ObjectType objectType = object.asObjectable(); ShadowType shadow; @@ -255,7 +256,7 @@ private ContainerWrapper crea } else { throw new SchemaException("Something very strange happenned. Association contianer in the " + objectType.getClass().getSimpleName() + "?"); } - Task task = modelServiceLocator.createSimpleTask("Load resource ref"); +// Task task = modelServiceLocator.createSimpleTask("Load resource ref"); //TODO: is it safe to case modelServiceLocator to pageBase? PrismObject resource = WebModelServiceUtils.loadObject(shadow.getResourceRef(), modelServiceLocator, task, result); @@ -275,11 +276,11 @@ private ContainerWrapper crea } if (prismContainer != null) { - return cwf.createContainerWrapper(prismContainer, objectStatus, ContainerStatus.MODIFYING, newPath); + return cwf.createContainerWrapper(prismContainer, objectStatus, ContainerStatus.MODIFYING, newPath, task); } prismContainer = containerDef.instantiate(); - return cwf.createContainerWrapper(prismContainer, objectStatus, ContainerStatus.ADDING, newPath); + return cwf.createContainerWrapper(prismContainer, objectStatus, ContainerStatus.ADDING, newPath, task); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismContainerHeaderPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismContainerHeaderPanel.java index 4d02ccbba70..35e81a87243 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismContainerHeaderPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismContainerHeaderPanel.java @@ -5,6 +5,7 @@ import org.apache.wicket.model.IModel; import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; public class PrismContainerHeaderPanel extends PrismHeaderPanel>{ @@ -47,7 +48,10 @@ public void onClick(AjaxRequestTarget target) { private void addValue(AjaxRequestTarget target) { ContainerWrapperFactory cwf = new ContainerWrapperFactory(getPageBase()); ContainerWrapper containerWrapper = getModelObject(); - ContainerValueWrapper newContainerValue = cwf.createContainerValueWrapper(containerWrapper, containerWrapper.getItem().createNewValue(), containerWrapper.getObjectStatus(), ValueStatus.ADDED, containerWrapper.getPath()); + Task task = getPageBase().createSimpleTask("Creating new container"); + ContainerValueWrapper newContainerValue = cwf.createContainerValueWrapper(containerWrapper, + containerWrapper.getItem().createNewValue(), containerWrapper.getObjectStatus(), ValueStatus.ADDED, + containerWrapper.getPath(), task); newContainerValue.setShowEmpty(true, false); getModelObject().addValue(newContainerValue); onButtonClick(target); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismContainerValueHeaderPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismContainerValueHeaderPanel.java index 2233478e662..0213808629c 100755 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismContainerValueHeaderPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismContainerValueHeaderPanel.java @@ -16,7 +16,11 @@ import com.evolveum.midpoint.gui.api.GuiStyleConstants; import com.evolveum.midpoint.gui.api.component.togglebutton.ToggleIconButton; +import com.evolveum.midpoint.gui.api.page.PageBase; import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; import com.evolveum.midpoint.xml.ns._public.common.common_3.MetadataType; import org.apache.wicket.model.Model; @@ -120,9 +124,10 @@ public boolean isOn() { @Override public void onClick(AjaxRequestTarget target) { - ContainerValueWrapper containerValueWrapper = PrismContainerValueHeaderPanel.this.getModelObject(); - containerValueWrapper.setSorted(!containerValueWrapper.isSorted()); - containerValueWrapper.sort(); + ContainerValueWrapper containerValueWrapper = PrismContainerValueHeaderPanel.this.getModelObject(); + containerValueWrapper.setSorted(!containerValueWrapper.isSorted()); + containerValueWrapper.sort(); + containerValueWrapper.computeStripes(); onButtonClick(target); } @@ -260,7 +265,7 @@ protected void reloadParentContainerPanel(AjaxRequestTarget target){ protected void addNewContainerValuePerformed(AjaxRequestTarget ajaxRequestTarget){ isChildContainersSelectorPanelVisible = false; getModelObject().setShowEmpty(true, false); - getModelObject().addNewChildContainerValue(getSelectedContainerQName(), getPageBase()); + createNewContainerValue(getModelObject(), getSelectedContainerQName()); ajaxRequestTarget.add(getChildContainersSelectorPanel().getParent()); } @@ -283,9 +288,34 @@ private void onShowEmptyClick(AjaxRequestTarget target) { ContainerValueWrapper wrapper = PrismContainerValueHeaderPanel.this.getModelObject(); wrapper.setShowEmpty(!wrapper.isShowEmpty(), false); + wrapper.computeStripes(); onButtonClick(target); } + + public void createNewContainerValue(ContainerValueWrapper containerValueWrapper, QName path){ + ContainerWrapper childContainerWrapper = containerValueWrapper.getContainer().findContainerWrapper(new ItemPath(getPath(), path)); + if (childContainerWrapper == null){ + return; + } + boolean isSingleValue = childContainerWrapper.getItemDefinition().isSingleValue(); + if (isSingleValue){ + return; + } + PrismContainerValue newContainerValue = childContainerWrapper.getItem().createNewValue(); + + Task task = getPageBase().createSimpleTask("Creating new container value wrapper"); + + ContainerWrapperFactory factory = new ContainerWrapperFactory(getPageBase()); + ContainerValueWrapper newValueWrapper = factory.createContainerValueWrapper(childContainerWrapper, + newContainerValue, containerValueWrapper.getObjectStatus(), + ValueStatus.ADDED, new ItemPath(path), task); + newValueWrapper.setShowEmpty(true, false); + newValueWrapper.computeStripes(); + childContainerWrapper.getValues().add(newValueWrapper); + + } + } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java index 80faef3e26a..638545aa39e 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/PrismValuePanel.java @@ -40,6 +40,7 @@ import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField; import org.apache.wicket.extensions.yui.calendar.DateTimeField; import org.apache.wicket.feedback.ComponentFeedbackMessageFilter; +import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.FormComponent; @@ -208,6 +209,9 @@ public String getObject() { } private boolean isAccessible(ItemDefinition def, ContainerStatus status) { + if (def.getName().equals(ConstructionType.F_KIND) || def.getName().equals(ConstructionType.F_INTENT)){ + return false; + } switch (status) { case ADDING: if (!def.canAdd()) { @@ -245,6 +249,15 @@ public boolean isEnabled() { return object == null || isAccessible(def, object.getStatus()); } + + @Override + public void onComponentTag(Component component, ComponentTag tag) { + if (component instanceof TextField && !isEnabled()) { + tag.remove("disabled"); + tag.append("class", "input-readonly", " "); + tag.append("readonly", "readonly", " "); + } + } }); } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/ConfigurationStep.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/ConfigurationStep.java index 7ae7f769993..d376d487195 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/ConfigurationStep.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/ConfigurationStep.java @@ -133,11 +133,12 @@ private List createConfigContainerWrappers() throws SchemaExce ContainerWrapperFactory cwf = new ContainerWrapperFactory(parentPage); ContainerWrapper containerWrapper; + Task task = getPageBase().createSimpleTask("Creting configuration container"); if (container != null) { - containerWrapper = cwf.createContainerWrapper(container, ContainerStatus.MODIFYING, ContainerStatus.MODIFYING, containerPath, parentPage.isReadOnly()); + containerWrapper = cwf.createContainerWrapper(container, ContainerStatus.MODIFYING, ContainerStatus.MODIFYING, containerPath, parentPage.isReadOnly(), task); } else { container = containerDef.instantiate(); - containerWrapper = cwf.createContainerWrapper(container, ContainerStatus.ADDING, ContainerStatus.ADDING, containerPath, parentPage.isReadOnly()); + containerWrapper = cwf.createContainerWrapper(container, ContainerStatus.ADDING, ContainerStatus.ADDING, containerPath, parentPage.isReadOnly(), task); containerWrapper.setShowEmpty(true, true); } containerWrappers.add(containerWrapper); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/component/DuplicateObjectTypeDetector.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/component/DuplicateObjectTypeDetector.java index 75d76fe12ff..6bc2e4606d8 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/component/DuplicateObjectTypeDetector.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/component/DuplicateObjectTypeDetector.java @@ -35,7 +35,7 @@ public String getDuplicatesList() { return sb.toString(); } - private class ObjectTypeRecord { + private static class ObjectTypeRecord { @NotNull public final ShadowKindType kind; @NotNull public final String intent; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/dto/WizardIssuesDto.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/dto/WizardIssuesDto.java index 3748fd3969e..ea6b69f8ed8 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/dto/WizardIssuesDto.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/dto/WizardIssuesDto.java @@ -131,7 +131,7 @@ static Severity fromModel(@NotNull com.evolveum.midpoint.model.api.validator.Iss } } - public class Issue implements Serializable { + public static class Issue implements Serializable { @NotNull private final Severity severity; @NotNull private final String text; @Nullable private final Class relatedStep; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/PageAdminObjectDetails.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/PageAdminObjectDetails.java index 3c6463b2cd9..19acf39b19e 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/PageAdminObjectDetails.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/PageAdminObjectDetails.java @@ -352,7 +352,7 @@ protected ObjectWrapper loadObjectWrapper(PrismObject objectToEdit, boolea result.recordFatalError("Couldn't get user.", ex); LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load user", ex); try { - wrapper = owf.createObjectWrapper("pageAdminFocus.focusDetails", null, object, null, null, status); + wrapper = owf.createObjectWrapper("pageAdminFocus.focusDetails", null, object, null, null, status, task); } catch (SchemaException e) { throw new SystemException(e.getMessage(), e); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/PageCase.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/PageCase.java index 8ec1a4ba89c..c08fdc1c51e 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/PageCase.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/PageCase.java @@ -135,7 +135,7 @@ private ObjectWrapper loadCase() { result.recordFatalError("Couldn't get case.", ex); LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load case", ex); try { - wrapper = owf.createObjectWrapper("PageCase.details", null, caseInstance, null, null, status); + wrapper = owf.createObjectWrapper("PageCase.details", null, caseInstance, null, null, status, task); } catch (SchemaException e) { throw new SystemException(e.getMessage(), e); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/DefinitionStagePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/DefinitionStagePanel.java index 05404102c1a..9063b8e4823 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/DefinitionStagePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/DefinitionStagePanel.java @@ -201,7 +201,7 @@ public String getObject() { } - private class NoOffsetPrismReferencePanel extends PrismPropertyPanel { + private static class NoOffsetPrismReferencePanel extends PrismPropertyPanel { public NoOffsetPrismReferencePanel(String id, IModel propertyModel, Form form, PageBase pageBase) { super(id, propertyModel, form, null, pageBase); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageDebugList.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageDebugList.java index 6243c143de1..f4d63aa116d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageDebugList.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageDebugList.java @@ -635,7 +635,6 @@ private void deleteAllIdentitiesConfirmed(AjaxRequestTarget target, DeleteAllDto } target.add(getFeedbackPanel()); - result.recomputeStatus(); showResult(result); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/dto/SystemConfigurationDto.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/dto/SystemConfigurationDto.java index ba2ec9793e9..ff8677d67db 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/dto/SystemConfigurationDto.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/dto/SystemConfigurationDto.java @@ -64,7 +64,7 @@ public class SystemConfigurationDto implements Serializable { public static final String F_ADMIN_GUI_CONFIGURATION = "adminGuiConfiguration"; private AEPlevel aepLevel; - private class CleanupInfo implements Serializable { + private static class CleanupInfo implements Serializable { String ageValue; Integer records; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/home/PageMyPasswordQuestions.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/home/PageMyPasswordQuestions.java index a7a2db94929..f1cadba3d0a 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/home/PageMyPasswordQuestions.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/home/PageMyPasswordQuestions.java @@ -506,7 +506,7 @@ private ObjectWrapper loadUserWrapper(PrismObject userToEdit) { result.recordFatalError("Couldn't get user.", ex); LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load user", ex); try { - wrapper = owf.createObjectWrapper("pageMyPasswordQuestions.userDetails", null, user, null, null, status); + wrapper = owf.createObjectWrapper("pageMyPasswordQuestions.userDetails", null, user, null, null, status, task); } catch (SchemaException e) { throw new SystemException(e.getMessage(), e); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/component/RunReportPopupPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/component/RunReportPopupPanel.java index ba4fe74c868..faf7062f4a0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/component/RunReportPopupPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/component/RunReportPopupPanel.java @@ -587,7 +587,7 @@ public Component getComponent() { return this; } - class LookupReportPropertyModel extends LookupPropertyModel { + static class LookupReportPropertyModel extends LookupPropertyModel { private static final long serialVersionUID = 1L; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/component/TestConnectionMessagesPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/component/TestConnectionMessagesPanel.java index 8aa1f506988..4bedc907706 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/component/TestConnectionMessagesPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/component/TestConnectionMessagesPanel.java @@ -160,7 +160,7 @@ public void initResultsPanel(RepeatingView resultView, List opresults, } } - private class ConnectorStruct implements Serializable { + private static class ConnectorStruct implements Serializable { private String connectorName; private List connectorResultsDto; } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/roles/RoleGovernanceRelationsPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/roles/RoleGovernanceRelationsPanel.java index 4d56ebdb8de..c5c728354f9 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/roles/RoleGovernanceRelationsPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/roles/RoleGovernanceRelationsPanel.java @@ -232,7 +232,7 @@ protected boolean isGovernance(){ return true; } - class RoleRelationSelectionDto implements Serializable { + static class RoleRelationSelectionDto implements Serializable { private static final long serialVersionUID = 1L; private boolean approver; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTaskEdit.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTaskEdit.java index ab5100f9402..83669396b05 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTaskEdit.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTaskEdit.java @@ -335,7 +335,7 @@ protected ObjectWrapper loadObjectWrapper(PrismObject object result.recordFatalError("Couldn't get user.", ex); LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load user", ex); try { - wrapper = owf.createObjectWrapper("pageAdminFocus.focusDetails", null, object, null, null, ContainerStatus.MODIFYING); + wrapper = owf.createObjectWrapper("pageAdminFocus.focusDetails", null, object, null, null, ContainerStatus.MODIFYING, task); } catch (SchemaException e) { throw new SystemException(e.getMessage(), e); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/dto/TaskDto.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/dto/TaskDto.java index 65955412216..312e6459f0e 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/dto/TaskDto.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/dto/TaskDto.java @@ -311,7 +311,21 @@ private void fillInObjectRefAttributes(TaskType taskType, TaskDtoProviderOptions } public String getTaskObjectName(TaskType taskType, PageBase pageBase, Task opTask, OperationResult thisOpResult) { - return WebModelServiceUtils.resolveReferenceName(taskType.getObjectRef(), pageBase, opTask, thisOpResult); + OperationResult currentResult; + ObjectReferenceType objectRef; + if (taskType.getWorkflowContext() != null) { + // For workflow-related tasks the task object might not be created yet (MID-4512). The simplest way + // of avoiding displaying the error is to use a separate operation result. + currentResult = new OperationResult(TaskDto.class.getName() + ".getTaskObjectName"); + objectRef = taskType.getWorkflowContext().getObjectRef(); // here should be the name present (important for objects that are to be created) + } else { + currentResult = thisOpResult; + objectRef = null; + } + if (objectRef == null) { // either not a workflow task, or wfc.objectRef does not exist + objectRef = taskType.getObjectRef(); + } + return WebModelServiceUtils.resolveReferenceName(objectRef, pageBase, opTask, currentResult); } private void fillInParentTaskAttributes(TaskType taskType, diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/dto/GenericHandlerDto.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/dto/GenericHandlerDto.java index 882331fe9d5..3a663bf244b 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/dto/GenericHandlerDto.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/dto/GenericHandlerDto.java @@ -20,6 +20,7 @@ import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.util.CloneUtil; +import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.web.component.prism.*; @@ -104,7 +105,8 @@ public GenericHandlerDto(TaskDto taskDto, @NotNull List items, PageBase pa } PrismContainerDefinition containerDefinition = new PrismContainerDefinitionImpl<>(new QName("Handler data"), ctd, prismContext); container.setDefinition(containerDefinition); - containerWrapper = cwf.createContainerWrapper(container, ContainerStatus.MODIFYING, ContainerStatus.MODIFYING, ItemPath.EMPTY_PATH, true); + Task task = pageBase.createSimpleTask("Adding new container wrapper"); + containerWrapper = cwf.createContainerWrapper(container, ContainerStatus.MODIFYING, ContainerStatus.MODIFYING, ItemPath.EMPTY_PATH, true, task); } public ContainerWrapper getContainer() { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/login/PageSelfRegistration.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/login/PageSelfRegistration.java index f4cc279e0cd..32d10688df0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/login/PageSelfRegistration.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/login/PageSelfRegistration.java @@ -691,7 +691,7 @@ private String generateNonce(NonceCredentialsPolicyType n } policy = valuePolicy.asObjectable(); } - + return getModelInteractionService().generateValue(policy, 24, false, user, "nonce generation (registration)", task, result); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageAccountActivation.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageAccountActivation.java index f1327e20302..9377064a57c 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageAccountActivation.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageAccountActivation.java @@ -43,6 +43,7 @@ import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; import com.evolveum.midpoint.model.api.AuthenticationEvaluator; import com.evolveum.midpoint.model.api.context.PasswordAuthenticationContext; +import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SelectorOptions; @@ -93,6 +94,11 @@ public class PageAccountActivation extends PageBase { public PageAccountActivation(PageParameters params) { UserType user = loadUser(params); + + if (user == null) { + getSession().error(getString("PageAccountActivation.account.activation.failed")); + throw new RestartResponseException(PageLogin.class); + } userModel = new LoadableModel(false) { @@ -119,11 +125,16 @@ private UserType loadUser(PageParameters params){ OperationResult result = new OperationResult(LOAD_USER); return runPrivileged(new Producer() { + private static final long serialVersionUID = 1L; @Override public UserType run() { Collection> options = SelectorOptions.createCollection(UserType.F_LINK_REF, GetOperationOptions.createResolve()); - return WebModelServiceUtils.loadObject(UserType.class, userOid, options, PageAccountActivation.this, task, result).asObjectable(); + PrismObject user = WebModelServiceUtils.loadObject(UserType.class, userOid, options, PageAccountActivation.this, task, result); + if (user == null) { + return null; + } + return user.asObjectable(); } }); @@ -143,7 +154,7 @@ public boolean isVisible() { }); - Form form = new com.evolveum.midpoint.web.component.form.Form<>(ID_MAIN_FORM); + Form form = new com.evolveum.midpoint.web.component.form.Form<>(ID_MAIN_FORM); activationContainer.add(form); Label usernamePanel = new Label(ID_NAME, createStringResource("PageAccountActivation.activate.accounts.label", new PropertyModel<>(userModel, "name.orig"))); @@ -225,7 +236,7 @@ public void onClick(AjaxRequestTarget target) { private String getOidFromParameter(PageParameters params){ if (params == null || params.isEmpty()) { - LOGGER.error("No page paraeters found for account activation. No user to activate his/her accounts"); + LOGGER.error("No page parameters found for account activation. No user to activate his/her accounts"); return null; } @@ -272,6 +283,7 @@ private void propagatePassword(AjaxRequestTarget target, } OperationResult result = runPrivileged(new Producer() { + private static final long serialVersionUID = 1L; @Override public OperationResult run() { @@ -305,7 +317,7 @@ private List getShadowsToActivate(){ if (shadowsToActivate == null || shadowsToActivate.isEmpty()) { return new ArrayList<>(); } - return shadowsToActivate.parallelStream().filter(shadow -> shadow.getLifecycleState().equals(SchemaConstants.LIFECYCLE_PROPOSED)).collect(Collectors.toList()); + return shadowsToActivate.parallelStream().filter(shadow -> SchemaConstants.LIFECYCLE_PROPOSED.equals(shadow.getLifecycleState())).collect(Collectors.toList()); } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageAssignmentsList.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageAssignmentsList.java index 06b1181fb47..bda53a579cd 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageAssignmentsList.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PageAssignmentsList.java @@ -260,7 +260,7 @@ private void onSingleUserRequestPerformed(AjaxRequestTarget target) { storage.getRoleCatalog().getAssignmentShoppingCart().clear(); } catch (Exception e) { LoggingUtils.logUnexpectedException(LOGGER, "Could not save assignments ", e); - error("Could not save assignments. Reason: " + e); + error(createStringResource("PageAssignmentsList.saveAssignmentsError").getString() + e.getLocalizedMessage()); target.add(getFeedbackPanel()); } finally { result.recomputeStatus(); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/component/DashboardSearchPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/component/DashboardSearchPanel.java index c44a607078c..f832046dec1 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/component/DashboardSearchPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/component/DashboardSearchPanel.java @@ -43,6 +43,11 @@ public class DashboardSearchPanel extends BasePanel { public DashboardSearchPanel(String id) { super(id); + } + + @Override + protected void onInitialize(){ + super.onInitialize(); SEARCH_TYPES = Arrays.asList( createStringResource("PageDashboard.search.users").getString(), createStringResource("PageDashboard.search.resources").getString(), diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/MidPointApplication.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/MidPointApplication.java index 327a837345b..92dc6437125 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/MidPointApplication.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/MidPointApplication.java @@ -357,18 +357,18 @@ private static List loadLocaleDescriptors(Resource resource) t map.put(key, properties.getProperty(key)); } - for (String key : localeMap.keySet()) { - Map localeDefinition = localeMap.get(key); - if (!localeDefinition.containsKey(key + PROP_NAME) - || !localeDefinition.containsKey(key + PROP_FLAG)) { + for (Map.Entry> entry : localeMap.entrySet()) { + Map localeDefinition = entry.getValue(); + if (!localeDefinition.containsKey(entry + PROP_NAME) + || !localeDefinition.containsKey(entry + PROP_FLAG)) { continue; } LocaleDescriptor descriptor = new LocaleDescriptor( - localeDefinition.get(key + PROP_NAME), - localeDefinition.get(key + PROP_FLAG), - localeDefinition.get(key + PROP_DEFAULT), - WebComponentUtil.getLocaleFromString(key) + localeDefinition.get(entry + PROP_NAME), + localeDefinition.get(entry + PROP_FLAG), + localeDefinition.get(entry + PROP_DEFAULT), + WebComponentUtil.getLocaleFromString(entry.getKey()) ); locales.add(descriptor); } diff --git a/gui/admin-gui/src/main/resources/localization/Midpoint.properties b/gui/admin-gui/src/main/resources/localization/Midpoint.properties index 7fdc133e23d..2d7775ca708 100755 --- a/gui/admin-gui/src/main/resources/localization/Midpoint.properties +++ b/gui/admin-gui/src/main/resources/localization/Midpoint.properties @@ -3720,6 +3720,7 @@ PageAssignmentsList.submitButton=Submit PageAssignmentsList.resolveConflicts=Resolve conflicts PageAssignmentsList.commentHere=Comment here... PageAssignmentsList.requestComment=Request comment (optional) +PageAssignmentsList.saveAssignmentsError=Could not save assignments. Reason: AssignmentShoppingCartPanel.treeTitle=Role catalog AssignmentViewType.ROLE_CATALOG_VIEW=Role catalog view AssignmentViewType.ROLE_TYPE=All roles view @@ -4023,3 +4024,4 @@ pageAdminFocus.dataProtection=Data protection PageInternals.title.cache=Caches PageInternals.tab.cache=Cache management InternalsCachePanel.button.clearCaches=Clear caches +PageAccountActivation.user.not.found=Unexpected problem occurs. Please contact system administrator. diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/SerializationOptions.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/SerializationOptions.java index c4f7b66aa73..7e84b0e902e 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/SerializationOptions.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/SerializationOptions.java @@ -36,7 +36,7 @@ public void setSerializeReferenceNames(boolean serializeReferenceNames) { this.serializeReferenceNames = serializeReferenceNames; } - public static SerializationOptions createSerializeReferenceNames(){ + public static SerializationOptions createSerializeReferenceNames() { SerializationOptions serializationOptions = new SerializationOptions(); serializationOptions.setSerializeReferenceNames(true); return serializationOptions; @@ -54,7 +54,7 @@ public void setSerializeCompositeObjects(boolean serializeCompositeObjects) { this.serializeCompositeObjects = serializeCompositeObjects; } - public static SerializationOptions createSerializeCompositeObjects(){ + public static SerializationOptions createSerializeCompositeObjects() { SerializationOptions serializationOptions = new SerializationOptions(); serializationOptions.setSerializeCompositeObjects(true); return serializationOptions; diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/lex/json/AbstractJsonLexicalProcessor.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/lex/json/AbstractJsonLexicalProcessor.java index 7e49cb42be6..7b2ef316078 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/lex/json/AbstractJsonLexicalProcessor.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/lex/json/AbstractJsonLexicalProcessor.java @@ -105,7 +105,7 @@ private List readInternal(@NotNull ParserSource source, @NotNull Pars } } - private class IterativeParsingContext { + private static class IterativeParsingContext { final RootXNodeHandler handler; boolean dataSent; // true if we really found the list of objects and sent it out String defaultNamespace; // default namespace, if present @@ -621,7 +621,7 @@ private JsonParser configureParser(JsonParser parser) { //region Serialization implementation - class JsonSerializationContext { + static class JsonSerializationContext { @NotNull final JsonGenerator generator; @NotNull private final SerializationContext prismSerializationContext; private String currentNamespace; diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/ItemPathHolder.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/ItemPathHolder.java index f786dfe18f4..53e58a6b558 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/ItemPathHolder.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/ItemPathHolder.java @@ -543,17 +543,19 @@ public ItemPathHolder transposedPath(List parentPath) { private void addExplicitNsDeclarations(StringBuilder sb) { if (explicitNamespaceDeclarations != null) { - for (String prefix : explicitNamespaceDeclarations.keySet()) { + for (Map.Entry declaration : explicitNamespaceDeclarations.entrySet()) { sb.append("declare "); + String prefix = declaration.getKey(); + String value = declaration.getValue(); if (prefix.equals("")) { sb.append("default namespace '"); - sb.append(explicitNamespaceDeclarations.get(prefix)); + sb.append(value); sb.append("'; "); } else { sb.append("namespace "); sb.append(prefix); sb.append("='"); - sb.append(explicitNamespaceDeclarations.get(prefix)); + sb.append(value); sb.append("'; "); } } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java index 5e13132401c..8eec4ebac67 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/path/ItemPath.java @@ -401,7 +401,7 @@ public CompareResult compareComplexOld(ItemPath otherPath) { /** * Alternative to normalization: reads the same sequence of segments of 'path' as segments of 'path.normalize()' */ - private class ItemPathNormalizingIterator implements Iterator { + private static class ItemPathNormalizingIterator implements Iterator { final ItemPath path; private int i = 0; private boolean nextIsArtificialId = false; diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/schema/XmlEntityResolverImpl.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/schema/XmlEntityResolverImpl.java index 8de4688e81d..1b88f0e1900 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/schema/XmlEntityResolverImpl.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/schema/XmlEntityResolverImpl.java @@ -166,7 +166,7 @@ public InputSource resolveResourceUsingBuiltinResolver(String type, String names return inputSource; } - class Input implements LSInput { + static class Input implements LSInput { private String publicId; private String systemId; diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/xml/XsdTypeMapper.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/xml/XsdTypeMapper.java index 43862c35b6a..206650d1377 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/xml/XsdTypeMapper.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/xml/XsdTypeMapper.java @@ -152,13 +152,13 @@ public static QName determineQNameWithNs(QName xsdType){ public static Class getXsdToJavaMapping(QName xsdType) { Class clazz = xsdToJavaTypeMap.get(xsdType); if (clazz == null){ - Set keys = xsdToJavaTypeMap.keySet(); - for (Iterator iterator = keys.iterator(); iterator.hasNext();){ - QName key = iterator.next(); - if (QNameUtil.match(key, xsdType)){ - return xsdToJavaTypeMap.get(key); - } - } + Set> entries = xsdToJavaTypeMap.entrySet(); + for (Map.Entry entry : entries) { + QName key = entry.getKey(); + if (QNameUtil.match(key, xsdType)){ + return entry.getValue(); + } + } } return xsdToJavaTypeMap.get(xsdType); } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/xnode/MapXNode.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/xnode/MapXNode.java index 111f89fa9b9..a39afbba232 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/xnode/MapXNode.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/xnode/MapXNode.java @@ -395,7 +395,7 @@ public RootXNode getSingleEntryMapAsRoot() { return new RootXNode(key, get(key)); } - private class Entry implements Map.Entry, Serializable { + private static class Entry implements Map.Entry, Serializable { private QName key; private XNode value; diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/constants/SchemaConstants.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/constants/SchemaConstants.java index 4302afd2f8d..717e66b852c 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/constants/SchemaConstants.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/constants/SchemaConstants.java @@ -266,6 +266,7 @@ public abstract class SchemaConstants { public static final QName CHANGE_CHANNEL_RECON = new QName(NS_PROVISIONING_CHANNEL, "reconciliation"); public static final String CHANGE_CHANNEL_RECON_URI = QNameUtil.qNameToUri(CHANGE_CHANNEL_RECON); public static final QName CHANGE_CHANNEL_RECOMPUTE = new QName(NS_PROVISIONING_CHANNEL, "recompute"); + public static final String CHANGE_CHANNEL_RECOMPUTE_URI = QNameUtil.qNameToUri(CHANGE_CHANNEL_RECOMPUTE); public static final QName CHANGE_CHANNEL_DISCOVERY = new QName(NS_PROVISIONING_CHANNEL, "discovery"); public static final String CHANGE_CHANNEL_DISCOVERY_URI = QNameUtil.qNameToUri(CHANGE_CHANNEL_DISCOVERY); public static final QName CHANGE_CHANNEL_IMPORT = new QName(NS_PROVISIONING_CHANNEL, "import"); @@ -358,6 +359,7 @@ public abstract class SchemaConstants { public static final QName MODEL_EXTENSION_OBJECT_TYPE = new QName(NS_MODEL_EXTENSION, "objectType"); public static final QName MODEL_EXTENSION_OBJECT_QUERY = new QName(NS_MODEL_EXTENSION, "objectQuery"); + public static final QName MODEL_EXTENSION_SEARCH_OPTIONS = new QName(NS_MODEL_EXTENSION, "searchOptions"); public static final QName MODEL_EXTENSION_ITERATION_METHOD = new QName(NS_MODEL_EXTENSION, "iterationMethod"); public static final QName MODEL_EXTENSION_OBJECT_DELTA = new QName(NS_MODEL_EXTENSION, "objectDelta"); public static final QName MODEL_EXTENSION_WORKER_THREADS = new QName(NS_MODEL_EXTENSION, "workerThreads"); @@ -464,7 +466,9 @@ public abstract class SchemaConstants { public static final QName C_FROM = new QName(NS_C, "from"); public static final QName C_ENCODED_FROM = new QName(NS_C, "encodedFrom"); public static final QName C_TO = new QName(NS_C, "to"); + public static final QName C_TO_LIST = new QName(NS_C, "toList"); public static final QName C_ENCODED_TO = new QName(NS_C, "encodedTo"); + public static final QName C_ENCODED_TO_LIST = new QName(NS_C, "encodedToList"); public static final QName C_MESSAGE_TEXT = new QName(NS_C, "messageText"); public static final QName C_ENCODED_MESSAGE_TEXT = new QName(NS_C, "encodedMessageText"); public static final QName C_MESSAGE = new QName(NS_C, "message"); diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd index aa6a0239f55..3abed5e53be 100755 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd @@ -18289,6 +18289,7 @@ + @@ -18352,6 +18353,41 @@ + + + + Specifies whether "distinct" option should be used in database searches. + + + + + + + Automatic use of distinct option. The code would use distinct option + in case that the query suggest that there is possibility of search + result duplication. + Note: use of "distinct" option will produce cleaner (not duplicated) + search results. But its use may have performance impact. + + + + + + + + + + Disable use of "distinct" option. The option would never be used, + even if there is a risk of search result duplication. + + + + + + + + + diff --git a/infra/schema/src/main/resources/xml/ns/public/model/extension-3.xsd b/infra/schema/src/main/resources/xml/ns/public/model/extension-3.xsd index 85330e2fc37..88d8dcd451b 100644 --- a/infra/schema/src/main/resources/xml/ns/public/model/extension-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/model/extension-3.xsd @@ -141,6 +141,20 @@ + + + + Options to be used for object search (if supported by particular task handler). + + + Search options + + 0 + 1 + + + + diff --git a/infra/util/src/main/java/com/evolveum/midpoint/util/MiscUtil.java b/infra/util/src/main/java/com/evolveum/midpoint/util/MiscUtil.java index 9d69759df04..82f2ff9b36b 100644 --- a/infra/util/src/main/java/com/evolveum/midpoint/util/MiscUtil.java +++ b/infra/util/src/main/java/com/evolveum/midpoint/util/MiscUtil.java @@ -27,6 +27,9 @@ import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; import java.io.*; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; import java.nio.channels.FileChannel; import java.util.*; import java.util.Map.Entry; @@ -697,4 +700,13 @@ public static Set filter(Set input, Predicate predicate) { public static Collection nonNullValues(@NotNull Collection values) { return values.stream().filter(Objects::nonNull).collect(Collectors.toList()); } + + public static URL toUrlUnchecked(URI uri) { + try { + return uri.toURL(); + } catch (MalformedURLException e) { + throw new SystemException(e); + } + } + } diff --git a/infra/util/src/main/java/com/evolveum/midpoint/util/aspect/ProfilingDataManager.java b/infra/util/src/main/java/com/evolveum/midpoint/util/aspect/ProfilingDataManager.java index 34ceb5c9929..c5c35b1a70a 100644 --- a/infra/util/src/main/java/com/evolveum/midpoint/util/aspect/ProfilingDataManager.java +++ b/infra/util/src/main/java/com/evolveum/midpoint/util/aspect/ProfilingDataManager.java @@ -268,10 +268,10 @@ private synchronized void updateOverallStatistics(Map logMap, Subsystem subsystem, boolean afterTest){ - - for(String key: logMap.keySet()){ - if(logMap.get(key) != null && subsystem.equals(logMap.get(key).getSubsystem())){ - logMap.get(key).appendToLogger(afterTest); + for (Map.Entry usage : logMap.entrySet()){ + final MethodUsageStatistics value = usage.getValue(); + if(subsystem.equals(value.getSubsystem())){ + value.appendToLogger(afterTest); } } } diff --git a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationClosingTaskHandler.java b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationClosingTaskHandler.java index 69bbf0cb0c5..e7015e71998 100644 --- a/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationClosingTaskHandler.java +++ b/model/certification-impl/src/main/java/com/evolveum/midpoint/certification/impl/AccessCertificationClosingTaskHandler.java @@ -277,7 +277,7 @@ public void launch(AccessCertificationCampaignType campaign, OperationResult par LOGGER.trace("Closing task for {} switched to background, control thread returning with task {}", toShortString(campaign), task); } - private class ObjectContext { + private static class ObjectContext { @NotNull final ObjectType object; @NotNull final List> modifications = new ArrayList<>(); @@ -286,7 +286,7 @@ private class ObjectContext { } } - private class RunContext { + private static class RunContext { final Task task; final Map objectContextMap = new HashMap<>(); final PerformerCommentsFormatter commentsFormatter; diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/stringpolicy/ValuePolicyProcessor.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/stringpolicy/ValuePolicyProcessor.java index e38ec233534..a1eb99a21ad 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/stringpolicy/ValuePolicyProcessor.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/stringpolicy/ValuePolicyProcessor.java @@ -125,11 +125,17 @@ public void setExpressionFactory(ExpressionFactory expressionFactory) { this.expressionFactory = expressionFactory; } - public String generate(ItemPath path, @NotNull ValuePolicyType policy, int defaultLength, boolean generateMinimalSize, + public String generate(ItemPath path, ValuePolicyType policy, int defaultLength, boolean generateMinimalSize, AbstractValuePolicyOriginResolver originResolver, String shortDesc, Task task, OperationResult parentResult) throws ExpressionEvaluationException, SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException { Context ctx = new Context(path); OperationResult result = parentResult.createSubresult(OP_GENERATE); + if (policy == null) { + //lets create some default policy + policy = new ValuePolicyType().stringPolicy(new StringPolicyType().limitations(new LimitationsType().maxLength(defaultLength).minLength(defaultLength))); + + } + StringPolicyType stringPolicy = policy.getStringPolicy(); int maxAttempts = DEFAULT_MAX_ATTEMPTS; if (stringPolicy.getLimitations() != null && stringPolicy.getLimitations().getMaxAttempts() != null) { @@ -554,9 +560,10 @@ private String generateAttempt(ValuePolicyType policy, int defaultLength, boolea * first in password */ Map> mustBeFirst = new HashMap<>(); - for (StringLimitType l : lims.keySet()) { - if (l.isMustBeFirst() != null && l.isMustBeFirst()) { - mustBeFirst.put(l, lims.get(l)); + for (Map.Entry> entry : lims.entrySet()) { + final StringLimitType key = entry.getKey(); + if (key.isMustBeFirst() != null && key.isMustBeFirst()) { + mustBeFirst.put(key, entry.getValue()); } } @@ -771,26 +778,28 @@ private Map> cardinalityCounter(Map password, Boolean skipMatchedLims, boolean uniquenessReached, OperationResult op) { HashMap counter = new HashMap<>(); - for (StringLimitType l : lims.keySet()) { + Map> mustBeFirst = new HashMap<>(); + for (Map.Entry> entry : lims.entrySet()) { + final StringLimitType key = entry.getKey(); int counterKey = 1; - List chars = lims.get(l); + List chars = entry.getValue(); int i = 0; if (null != password) { - i = charIntersectionCounter(lims.get(l), password); + i = charIntersectionCounter(entry.getValue(), password); } // If max is exceed then error unable to continue - if (l.getMaxOccurs() != null && i > l.getMaxOccurs()) { - OperationResult o = new OperationResult("Limitation check :" + l.getDescription()); + if (key.getMaxOccurs() != null && i > key.getMaxOccurs()) { + OperationResult o = new OperationResult("Limitation check :" + key.getDescription()); o.recordFatalError( - "Exceeded maximal value for this limitation. " + i + ">" + l.getMaxOccurs()); + "Exceeded maximal value for this limitation. " + i + ">" + key.getMaxOccurs()); op.addSubresult(o); return null; // if max is all ready reached or skip enabled for minimal skip // counting - } else if (l.getMaxOccurs() != null && i == l.getMaxOccurs()) { + } else if (key.getMaxOccurs() != null && i == key.getMaxOccurs()) { continue; // other cases minimum is not reached - } else if ((l.getMinOccurs() == null || i >= l.getMinOccurs()) && !skipMatchedLims) { + } else if ((key.getMinOccurs() == null || i >= key.getMinOccurs()) && !skipMatchedLims) { continue; } for (String s : chars) { @@ -803,9 +812,9 @@ private Map> cardinalityCounter(Map messages = new ArrayList<>(); private final List rules = new ArrayList<>(); } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/integrity/ObjectIntegrityCheckTaskHandler.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/integrity/ObjectIntegrityCheckTaskHandler.java index 492fecbd3c7..172ebb1790e 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/integrity/ObjectIntegrityCheckTaskHandler.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/integrity/ObjectIntegrityCheckTaskHandler.java @@ -94,7 +94,9 @@ protected ObjectQuery createQuery(ObjectIntegrityCheckResultHandler handler, Tas protected Collection> createSearchOptions( ObjectIntegrityCheckResultHandler resultHandler, TaskRunResult runResult, Task coordinatorTask, OperationResult opResult) { - return SelectorOptions.createCollection(GetOperationOptions.createAttachDiagData()); + Collection> optionsFromTask = createSearchOptionsFromTask(resultHandler, + runResult, coordinatorTask, opResult); + return SelectorOptions.updateRootOptions(optionsFromTask, opt -> opt.setAttachDiagData(true), GetOperationOptions::new); } @Override diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ContextFactory.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ContextFactory.java index 80c21899f58..e0bf3b7ae5b 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ContextFactory.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ContextFactory.java @@ -184,7 +184,7 @@ public LensContext createRecomputeFocusContext( LensFocusContext focusContext = syncContext.createFocusContext(); focusContext.setLoadedObject(focus); focusContext.setOid(focus.getOid()); - syncContext.setChannel(QNameUtil.qNameToUri(SchemaConstants.CHANGE_CHANNEL_RECOMPUTE)); + syncContext.setChannel(SchemaConstants.CHANGE_CHANNEL_RECOMPUTE_URI); syncContext.setDoReconciliationForAllProjections(ModelExecuteOptions.isReconcile(options)); return syncContext; } @@ -198,7 +198,7 @@ public LensContext createRecomputeProjectionContext( projectionContext.setLoadedObject(shadow); projectionContext.setOid(shadow.getOid()); projectionContext.setDoReconciliation(ModelExecuteOptions.isReconcile(options)); - syncContext.setChannel(QNameUtil.qNameToUri(SchemaConstants.CHANGE_CHANNEL_RECOMPUTE)); + syncContext.setChannel(SchemaConstants.CHANGE_CHANNEL_RECOMPUTE_URI); return syncContext; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/DependencyProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/DependencyProcessor.java index 3717605e39f..78e9f93d05c 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/DependencyProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/DependencyProcessor.java @@ -616,7 +616,7 @@ private boolean wasExecuted(LensProjectionContext accountContext){ return true; } - class DependencyAndSource { + static class DependencyAndSource { ResourceObjectTypeDependencyType dependency; LensProjectionContext sourceProjectionContext; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateRecorder.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateRecorder.java index d18248edba8..4b6cb69973b 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateRecorder.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/policy/PolicyStateRecorder.java @@ -129,7 +129,7 @@ private ComputationResult compute(@NotNull List rulesToReco return cr; } - private class ComputationResult { + private static class ComputationResult { final Set oldPolicySituations = new HashSet<>(); final Set newPolicySituations = new HashSet<>(); final Set oldTriggeredRules = new HashSet<>(); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/LiveSyncTaskHandler.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/LiveSyncTaskHandler.java index 358a11b89f1..60af7f17a32 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/LiveSyncTaskHandler.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/LiveSyncTaskHandler.java @@ -22,6 +22,7 @@ import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.provisioning.api.ProvisioningService; import com.evolveum.midpoint.schema.ResourceShadowDiscriminator; +import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition; import com.evolveum.midpoint.schema.result.OperationConstants; import com.evolveum.midpoint.schema.result.OperationResult; @@ -88,7 +89,11 @@ public TaskRunResult run(Task task) { TaskRunResult runResult = new TaskRunResult(); runResult.setOperationResult(opResult); - String resourceOid = task.getObjectOid(); + if (task.getChannel() == null) { + task.setChannel(SchemaConstants.CHANGE_CHANNEL_LIVE_SYNC_URI); + } + + String resourceOid = task.getObjectOid(); if (resourceOid == null) { LOGGER.error("Live Sync: No resource OID specified in the task"); opResult.recordFatalError("No resource OID specified in the task"); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/RecomputeTaskHandler.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/RecomputeTaskHandler.java index 3ac36d4e1e1..57f34a8586b 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/RecomputeTaskHandler.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/RecomputeTaskHandler.java @@ -17,6 +17,7 @@ import javax.annotation.PostConstruct; +import com.evolveum.midpoint.schema.constants.SchemaConstants; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -68,17 +69,10 @@ public class RecomputeTaskHandler extends AbstractSearchIterativeModelTaskHandle public static final String HANDLER_URI = ModelConstants.NS_SYNCHRONIZATION_TASK_PREFIX + "/recompute/handler-3"; - @Autowired - private TaskManager taskManager; - - @Autowired - private PrismContext prismContext; - - @Autowired - private ContextFactory contextFactory; - - @Autowired - private Clockwork clockwork; + @Autowired private TaskManager taskManager; + @Autowired private PrismContext prismContext; + @Autowired private ContextFactory contextFactory; + @Autowired private Clockwork clockwork; private static final transient Trace LOGGER = TraceManager.getTrace(RecomputeTaskHandler.class); @@ -142,4 +136,9 @@ private void recompute(PrismObject focalObject, ModelExecuteOptions o public String getCategoryName(Task task) { return TaskCategory.RECOMPUTATION; } + + @Override + protected String getDefaultChannel() { + return SchemaConstants.CHANGE_CHANNEL_RECOMPUTE_URI; + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/validator/ResourceValidatorImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/validator/ResourceValidatorImpl.java index aabf5e2026c..845024b2495 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/validator/ResourceValidatorImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/validator/ResourceValidatorImpl.java @@ -85,7 +85,7 @@ public class ResourceValidatorImpl implements ResourceValidator { @Autowired private PrismContext prismContext; - private class ResourceValidationContext { + private static class ResourceValidationContext { @NotNull final PrismObject resourceObject; @NotNull final ObjectReferenceType resourceRef; @NotNull final Scope scope; diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java index f6456840ba2..e60e91e6034 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java @@ -521,6 +521,7 @@ public class AbstractConfiguredModelIntegrationTest extends AbstractModelIntegra protected static final String AUTZ_DRINK_URL = QNameUtil.qNameToUri(AUTZ_DRINK_QNAME); protected static final String NOTIFIER_ACCOUNT_PASSWORD_NAME = "accountPasswordNotifier"; + protected static final String NOTIFIER_USER_PASSWORD_NAME = "userPasswordNotifier"; protected static final String NOTIFIER_ACCOUNT_ACTIVATION_NAME = "accountActivationNotifier"; private static final Trace LOGGER = TraceManager.getTrace(AbstractConfiguredModelIntegrationTest.class); @@ -727,31 +728,45 @@ protected void assertEvaluatedRole(Collection userAfter) throws Exception; @@ -1541,6 +1569,7 @@ public void test314RemovePasswordFail() throws Exception { } finally { setPasswordMinOccurs(null, task, result); } + assertNoUserPasswordNotifications(); } private void setPasswordMinOccurs(Integer value, Task task, OperationResult result) throws CommonException { @@ -1594,7 +1623,9 @@ public void test315RemovePassword() throws Exception { // this one is not changed assertDummyPassword(RESOURCE_DUMMY_UGLY_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_JACK_EMPLOYEE_NUMBER_NEW_GOOD); - assertNoPasswordNotifications(); + displayAllNotifications(); + assertNoAccountPasswordNotifications(); + assertNoUserPasswordNotifications(); } /* @@ -1643,8 +1674,9 @@ public void test316UserRecompute() throws Exception { // this one is not changed assertDummyPassword(RESOURCE_DUMMY_UGLY_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_JACK_EMPLOYEE_NUMBER_NEW_GOOD); - displayPasswordNotifications(); - assertNoPasswordNotifications(); + displayAccountPasswordNotifications(); + assertNoAccountPasswordNotifications(); + assertUserPasswordNotifications(1); } /** @@ -1689,11 +1721,12 @@ public void test318ChangeUserPassword() throws Exception { // this one is not changed assertDummyPassword(RESOURCE_DUMMY_UGLY_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_JACK_EMPLOYEE_NUMBER_NEW_GOOD); - displayPasswordNotifications(); - assertPasswordNotifications(2); - assertHasPasswordNotification(null, USER_JACK_USERNAME, USER_PASSWORD_VALID_3); - assertHasPasswordNotification(RESOURCE_DUMMY_RED_NAME, USER_JACK_USERNAME, USER_PASSWORD_VALID_3); + displayAccountPasswordNotifications(); + assertAccountPasswordNotifications(2); + assertHasAccountPasswordNotification(null, USER_JACK_USERNAME, USER_PASSWORD_VALID_3); + assertHasAccountPasswordNotification(RESOURCE_DUMMY_RED_NAME, USER_JACK_USERNAME, USER_PASSWORD_VALID_3); // not BLUE, it already has a password + assertSingleUserPasswordNotification(USER_JACK_USERNAME, USER_PASSWORD_VALID_3); } @Test @@ -1726,7 +1759,8 @@ public void test320ChangeEmployeeNumber() throws Exception { assertDummyPassword(RESOURCE_DUMMY_UGLY_NAME, ACCOUNT_JACK_DUMMY_USERNAME, "emp0000"); - assertSinglePasswordNotification(RESOURCE_DUMMY_UGLY_NAME, ACCOUNT_JACK_DUMMY_USERNAME, "emp0000"); + assertSingleAccountPasswordNotification(RESOURCE_DUMMY_UGLY_NAME, ACCOUNT_JACK_DUMMY_USERNAME, "emp0000"); + assertNoUserPasswordNotifications(); } @Test @@ -1759,7 +1793,8 @@ public void test330RemoveEmployeeNumber() throws Exception { assertDummyPassword(RESOURCE_DUMMY_UGLY_NAME, ACCOUNT_JACK_DUMMY_USERNAME, null); - assertNoPasswordNotifications(); + assertNoAccountPasswordNotifications(); + assertNoUserPasswordNotifications(); } /** @@ -1811,7 +1846,8 @@ public void test400AddUserRappWithAssignment() throws Exception { assertDefaultDummyAccount(USER_RAPP_USERNAME, USER_RAPP_FULLNAME, true); assertDummyPassword(null, USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); - assertSinglePasswordNotification(null, USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); + assertSingleAccountPasswordNotification(null, USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); + assertSingleUserPasswordNotification(USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); } /** @@ -1852,7 +1888,8 @@ public void test401UserRappRecompute() throws Exception { assertDefaultDummyAccount(USER_RAPP_USERNAME, USER_RAPP_FULLNAME, true); assertDummyPassword(null, USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); - assertNoPasswordNotifications(); + assertNoAccountPasswordNotifications(); + assertNoUserPasswordNotifications(); } /** @@ -1915,8 +1952,9 @@ public void test402AssignRappDummyRed() throws Exception { assertDummyPassword(null, USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); displayAllNotifications(); - assertSinglePasswordNotificationConditional(RESOURCE_DUMMY_RED_NAME, USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); + assertSingleAccountPasswordNotificationConditional(RESOURCE_DUMMY_RED_NAME, USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); assertAccountActivationNotification(RESOURCE_DUMMY_RED_NAME, USER_RAPP_USERNAME); + assertNoUserPasswordNotifications(); } /** @@ -1978,7 +2016,8 @@ public void test403UserRappRecompute() throws Exception { assertDefaultDummyAccount(USER_RAPP_USERNAME, USER_RAPP_FULLNAME, true); assertDummyPassword(null, USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); - assertNoPasswordNotifications(); + assertNoAccountPasswordNotifications(); + assertNoUserPasswordNotifications(); } /** @@ -2043,7 +2082,8 @@ public void test404InitializeRappDummyRed() throws Exception { assertDefaultDummyAccount(USER_RAPP_USERNAME, USER_RAPP_FULLNAME, true); assertDummyPassword(null, USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); - assertSingleInitializationPasswordNotification(RESOURCE_DUMMY_RED_NAME, USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); + assertSingleAccountInitializationPasswordNotification(RESOURCE_DUMMY_RED_NAME, USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); + assertNoUserPasswordNotifications(); } /** @@ -2106,7 +2146,8 @@ public void test405UserRappRecompute() throws Exception { assertDefaultDummyAccount(USER_RAPP_USERNAME, USER_RAPP_FULLNAME, true); assertDummyPassword(null, USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); - assertNoPasswordNotifications(); + assertNoAccountPasswordNotifications(); + assertNoUserPasswordNotifications(); } /** @@ -2156,7 +2197,8 @@ public void test410AssignRappDummyLifecycle() throws Exception { assertDefaultDummyAccount(USER_RAPP_USERNAME, USER_RAPP_FULLNAME, true); assertDummyPassword(null, USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); - assertSinglePasswordNotificationConditional(RESOURCE_DUMMY_LIFECYCLE_NAME, USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); + assertSingleAccountPasswordNotificationConditional(RESOURCE_DUMMY_LIFECYCLE_NAME, USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); + assertNoUserPasswordNotifications(); } @Test @@ -2232,8 +2274,8 @@ public void test412InitializeRappDummyLifecycle() throws Exception { assertDummyAccountShadowRepo(accountShadow, accountDefaultOid, USER_RAPP_USERNAME); assertShadowLifecycle(accountShadow, null); - assertSingleInitializationPasswordNotification(RESOURCE_DUMMY_LIFECYCLE_NAME, USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); - + assertSingleAccountInitializationPasswordNotification(RESOURCE_DUMMY_LIFECYCLE_NAME, USER_RAPP_USERNAME, USER_PASSWORD_VALID_1); + assertNoUserPasswordNotifications(); } @Test @@ -2303,7 +2345,8 @@ public void test414UserRappRecompute() throws Exception { assertDummyAccountShadowRepo(accountShadow, accountDefaultOid, USER_RAPP_USERNAME); assertShadowLifecycle(accountShadow, null); - assertNoPasswordNotifications(); + assertNoAccountPasswordNotifications(); + assertNoUserPasswordNotifications(); } @Test @@ -2373,7 +2416,8 @@ public void test416UserRappEmployeeTypeWreck() throws Exception { assertDummyAccountShadowRepo(accountShadow, accountDefaultOid, USER_RAPP_USERNAME); assertShadowLifecycle(accountShadow, null); - assertNoPasswordNotifications(); + assertNoAccountPasswordNotifications(); + assertNoUserPasswordNotifications(); } // TODO: employeeType->WRECK @@ -2436,8 +2480,9 @@ public void test500JackAssignResourceSouvenir() throws Exception { assertDummyPasswordConditional(RESOURCE_DUMMY_SOUVENIR_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_PASSWORD_VALID_3); displayAllNotifications(); - assertSinglePasswordNotificationConditional(RESOURCE_DUMMY_SOUVENIR_NAME, USER_JACK_USERNAME, USER_PASSWORD_VALID_3); + assertSingleAccountPasswordNotificationConditional(RESOURCE_DUMMY_SOUVENIR_NAME, USER_JACK_USERNAME, USER_PASSWORD_VALID_3); assertAccountActivationNotification(RESOURCE_DUMMY_SOUVENIR_NAME, USER_JACK_USERNAME); + assertNoUserPasswordNotifications(); } /** @@ -2481,7 +2526,9 @@ public void test502JackInitializeAccountSouvenir() throws Exception { assertEquals("Wrong comparison result", ItemComparisonResult.MATCH, comparisonResult); // TODO -// assertSingleInitializationPasswordNotification(RESOURCE_DUMMY_PASSWORD_CACHING_NAME, USER_JACK_USERNAME, PASSWORD_Alligator); +// assertSingleAccountInitializationPasswordNotification(RESOURCE_DUMMY_PASSWORD_CACHING_NAME, USER_JACK_USERNAME, PASSWORD_Alligator); + + assertNoUserPasswordNotifications(); } /** @@ -2522,8 +2569,9 @@ public void test510JackAssignResourceMaverick() throws Exception { assertDummyPasswordConditional(RESOURCE_DUMMY_MAVERICK_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_PASSWORD_VALID_3); displayAllNotifications(); - assertSinglePasswordNotificationConditional(RESOURCE_DUMMY_MAVERICK_NAME, USER_JACK_USERNAME, USER_PASSWORD_VALID_3); + assertSingleAccountPasswordNotificationConditional(RESOURCE_DUMMY_MAVERICK_NAME, USER_JACK_USERNAME, USER_PASSWORD_VALID_3); assertAccountActivationNotification(RESOURCE_DUMMY_MAVERICK_NAME, USER_JACK_USERNAME); + assertNoUserPasswordNotifications(); } /** @@ -2566,9 +2614,10 @@ public void test512JackInitializeAccountMaverickAlligator() throws Exception { assertUserPassword(userAfter, USER_PASSWORD_VALID_3); assertDummyPasswordConditional(RESOURCE_DUMMY_MAVERICK_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_PASSWORD_VALID_3); + assertNoUserPasswordNotifications(); // TODO -// assertSingleInitializationPasswordNotification(RESOURCE_DUMMY_PASSWORD_CACHING_NAME, USER_JACK_USERNAME, PASSWORD_Alligator); +// assertSingleAccountInitializationPasswordNotification(RESOURCE_DUMMY_PASSWORD_CACHING_NAME, USER_JACK_USERNAME, PASSWORD_Alligator); } /** @@ -2608,7 +2657,8 @@ public void test514JackInitializeAccountMaverickCrododile() throws Exception { assertDummyPassword(RESOURCE_DUMMY_MAVERICK_NAME, ACCOUNT_JACK_DUMMY_USERNAME, PASSWORD_CROCODILE); // TODO -// assertSingleInitializationPasswordNotification(RESOURCE_DUMMY_PASSWORD_CACHING_NAME, USER_JACK_USERNAME, PASSWORD_Alligator); +// assertSingleAccountInitializationPasswordNotification(RESOURCE_DUMMY_PASSWORD_CACHING_NAME, USER_JACK_USERNAME, PASSWORD_Alligator); + assertNoUserPasswordNotifications(); } /** @@ -2646,6 +2696,7 @@ public void test516JackChangePasswordResourceMaverickAlligator() throws Exceptio assertLinks(userAfter, 6); assertDummyPassword(RESOURCE_DUMMY_MAVERICK_NAME, USER_JACK_USERNAME, PASSWORD_CROCODILE); + assertNoUserPasswordNotifications(); } /** @@ -2676,6 +2727,7 @@ public void test518JackChangePasswordResourceMaverickGiantLizard() throws Except assertLinks(userAfter, 6); assertDummyPassword(RESOURCE_DUMMY_MAVERICK_NAME, USER_JACK_USERNAME, PASSWORD_GIANT_LIZARD); + assertNoUserPasswordNotifications(); } /** @@ -2709,7 +2761,8 @@ public void test530JackUnassignResourceSouvenir() throws Exception { display("User after", userAfter); assertAssignments(userAfter, 5); assertAssignedNoAccount(userAfter, RESOURCE_DUMMY_SOUVENIR_OID); - assertLinks(userAfter, 5); + assertLinks(userAfter, 5); + assertNoUserPasswordNotifications(); } /** @@ -2749,6 +2802,7 @@ public void test532JackChangePasswordResourceBlueAlligator() throws Exception { assertLinks(userAfter, 5); assertDummyPassword(RESOURCE_DUMMY_BLUE_NAME, USER_JACK_USERNAME, PASSWORD_ALLIGATOR); + assertNoUserPasswordNotifications(); } /** @@ -2782,6 +2836,7 @@ public void test535ModifyUserJackPasswordAlligator() throws Exception { assertUserPassword(userAfter, PASSWORD_ALLIGATOR); assertDummyPassword(RESOURCE_DUMMY_MAVERICK_NAME, ACCOUNT_JACK_DUMMY_USERNAME, PASSWORD_ALLIGATOR); + assertSingleUserPasswordNotification(USER_JACK_USERNAME, PASSWORD_ALLIGATOR); } /** @@ -2816,29 +2871,30 @@ public void test539JackUnassignResourceMaverick() throws Exception { assertAssignments(userAfter, 4); assertAssignedNoAccount(userAfter, RESOURCE_DUMMY_MAVERICK_OID); assertAssignedNoAccount(userAfter, RESOURCE_DUMMY_SOUVENIR_OID); - assertLinks(userAfter, 4); + assertLinks(userAfter, 4); + assertNoUserPasswordNotifications(); } /** * MID-4507 */ @Test - public void test550JackManyPassowrdChangesClear() throws Exception { - testJackManyPassowrdChanges("test550JackManyPassowrdChangesClear", "TesT550x", null); + public void test550JackManyPasswordChangesClear() throws Exception { + testJackManyPasswordChanges("test550JackManyPasswordChangesClear", "TesT550x", null); } /** * MID-4507 */ @Test - public void test552JackManyPassowrdChangesEncrypted() throws Exception { - testJackManyPassowrdChanges("test552JackManyPassowrdChangesEncrypted", "TesT552x", CredentialsStorageTypeType.ENCRYPTION); + public void test552JackManyPasswordChangesEncrypted() throws Exception { + testJackManyPasswordChanges("test552JackManyPasswordChangesEncrypted", "TesT552x", CredentialsStorageTypeType.ENCRYPTION); } /** * MID-4507 */ - public void testJackManyPassowrdChanges(final String TEST_NAME, String passwordPrefix, CredentialsStorageTypeType storageType) throws Exception { + public void testJackManyPasswordChanges(final String TEST_NAME, String passwordPrefix, CredentialsStorageTypeType storageType) throws Exception { displayTestTitle(TEST_NAME); // GIVEN @@ -2851,12 +2907,12 @@ public void testJackManyPassowrdChanges(final String TEST_NAME, String passwordP assertLinks(userBefore, 4); for (int i = 1; i < 10; i++) { - testJackManyPassowrdChangesAttempt(TEST_NAME, passwordPrefix, storageType, i); + testJackManyPasswordChangesAttempt(TEST_NAME, passwordPrefix, storageType, i); } } - private void testJackManyPassowrdChangesAttempt(String TEST_NAME, String passwordPrefix, CredentialsStorageTypeType storageType, int i) throws Exception { + private void testJackManyPasswordChangesAttempt(String TEST_NAME, String passwordPrefix, CredentialsStorageTypeType storageType, int i) throws Exception { Task task = createTask(TEST_NAME + "-" + i); OperationResult result = task.getResult(); @@ -2917,22 +2973,22 @@ protected void assertDummyPasswordConditionalGenerated(String instance, String u } } - protected void assertSinglePasswordNotificationConditional(String dummyResourceName, String username, String password) { + protected void assertSingleAccountPasswordNotificationConditional(String dummyResourceName, String username, String password) { if (isPasswordEncryption()) { - assertSinglePasswordNotification(dummyResourceName, username, password); + assertSingleAccountPasswordNotification(dummyResourceName, username, password); } } - protected void assertSinglePasswordNotificationConditionalGenerated(String dummyResourceName, String username, String password) { + protected void assertSingleAccountPasswordNotificationConditionalGenerated(String dummyResourceName, String username, String password) { if (isPasswordEncryption()) { - assertSinglePasswordNotification(dummyResourceName, username, password); + assertSingleAccountPasswordNotification(dummyResourceName, username, password); } else { - assertSinglePasswordNotificationGenerated(dummyResourceName, username); + assertSingleAccountPasswordNotificationGenerated(dummyResourceName, username); } } - private void assertSingleInitializationPasswordNotification(String dummyResourceName, String username, String password) { - assertSinglePasswordNotification(dummyResourceName, username, password); + private void assertSingleAccountInitializationPasswordNotification(String dummyResourceName, String username, String password) { + assertSingleAccountPasswordNotification(dummyResourceName, username, password); } protected abstract void assertAccountActivationNotification(String dummyResourceName, String username); @@ -2992,11 +3048,11 @@ public void test900ModifyUserElainePassword() throws Exception { assertUserPassword(userAfter, USER_PASSWORD_VALID_1); - displayPasswordNotifications(); - assertPasswordNotifications(3); - assertHasPasswordNotification(null, USER_ELAINE_USERNAME, USER_PASSWORD_VALID_1); - assertHasPasswordNotification(RESOURCE_DUMMY_RED_NAME, USER_ELAINE_USERNAME, USER_PASSWORD_VALID_1); - assertHasPasswordNotification(RESOURCE_DUMMY_BLUE_NAME, USER_ELAINE_USERNAME, USER_PASSWORD_VALID_1); + displayAccountPasswordNotifications(); + assertAccountPasswordNotifications(3); + assertHasAccountPasswordNotification(null, USER_ELAINE_USERNAME, USER_PASSWORD_VALID_1); + assertHasAccountPasswordNotification(RESOURCE_DUMMY_RED_NAME, USER_ELAINE_USERNAME, USER_PASSWORD_VALID_1); + assertHasAccountPasswordNotification(RESOURCE_DUMMY_BLUE_NAME, USER_ELAINE_USERNAME, USER_PASSWORD_VALID_1); } @Test @@ -3024,7 +3080,7 @@ public void test902SetPasswordMinAge() throws Exception { new ItemPath(SecurityPolicyType.F_CREDENTIALS, CredentialsPolicyType.F_PASSWORD, PasswordCredentialsPolicyType.F_MIN_AGE), XmlTypeConverter.createDuration("PT10M")); - assertNoPasswordNotifications(); + assertNoAccountPasswordNotifications(); } /** @@ -3061,7 +3117,8 @@ public void test904ModifyUserElainePasswordAgain() throws Exception { assertUserPassword(userAfter, USER_PASSWORD_VALID_1); - assertNoPasswordNotifications(); + assertNoAccountPasswordNotifications(); + assertNoUserPasswordNotifications(); } @Test @@ -3091,11 +3148,12 @@ public void test906ModifyUserElainePasswordLater() throws Exception { assertUserPassword(userAfter, USER_PASSWORD_VALID_3); - displayPasswordNotifications(); - assertPasswordNotifications(2); - assertHasPasswordNotification(null, USER_ELAINE_USERNAME, USER_PASSWORD_VALID_3); - assertHasPasswordNotification(RESOURCE_DUMMY_RED_NAME, USER_ELAINE_USERNAME, USER_PASSWORD_VALID_3); + displayAccountPasswordNotifications(); + assertAccountPasswordNotifications(2); + assertHasAccountPasswordNotification(null, USER_ELAINE_USERNAME, USER_PASSWORD_VALID_3); + assertHasAccountPasswordNotification(RESOURCE_DUMMY_RED_NAME, USER_ELAINE_USERNAME, USER_PASSWORD_VALID_3); // BLUE resource already has a password + assertSingleUserPasswordNotification(USER_ELAINE_USERNAME, USER_PASSWORD_VALID_3); } @@ -3127,6 +3185,7 @@ public void test910AddUserWithNoPasswordFail() throws Exception { } finally { setPasswordMinOccurs(null, task, result); } + assertNoUserPasswordNotifications(); } diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/TestPasswordDefaultHashing.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/TestPasswordDefaultHashing.java index eac3a5f20d8..0a914f88a2e 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/TestPasswordDefaultHashing.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/TestPasswordDefaultHashing.java @@ -69,7 +69,7 @@ protected void assertShadowLifecycle(PrismObject shadow, boolean foc * There is a RED account with a strong password * mapping. The reconcile and the strong mapping would normally try to set the short * password to RED account which would fail on RED account password policy. But not today. - * As we do not have password cleartexct in the user then no password change should happen. + * As we do not have password cleartext in the user then no password change should happen. * And everything should go smoothly. */ @Test @@ -134,7 +134,7 @@ protected void assert31xBluePasswordAfterPasswordChange(PrismObject us protected void assertAccountActivationNotification(String dummyResourceName, String username) { checkDummyTransportMessages(NOTIFIER_ACCOUNT_ACTIVATION_NAME, 1); String body = getDummyTransportMessageBody(NOTIFIER_ACCOUNT_ACTIVATION_NAME, 0); - String expectedPrefix = getExpectedPasswordNotificationBodyPrefix(dummyResourceName, username); + //String expectedPrefix = getExpectedAccountPasswordNotificationBodyPrefix(dummyResourceName, username); if (!body.contains("activat")) { fail("Activation not mentioned in "+dummyResourceName+" dummy account activation notification message : "+body); } diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/AbstractSynchronizationStoryTest.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/AbstractSynchronizationStoryTest.java index 5f17a7917fb..cac84473446 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/AbstractSynchronizationStoryTest.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/AbstractSynchronizationStoryTest.java @@ -184,6 +184,8 @@ public void test110AddDummyGreenAccountMancomb() throws Exception { assertUsers(6); // notifications + displayAllNotifications(); + assertSingleDummyTransportMessageContaining("simpleAccountNotifier-SUCCESS", "Channel: " + getExpectedChannel()); notificationManager.setDisabled(true); // checkDummyTransportMessages("userPasswordNotifier", 1); // password is generated by mapping (if there's none) // checkDummyTransportMessages("accountPasswordNotifier", 1); // account password is then set @@ -194,6 +196,8 @@ public void test110AddDummyGreenAccountMancomb() throws Exception { // checkDummyTransportMessages("simpleUserNotifier-ADD", 1); } + protected abstract String getExpectedChannel(); + @Test public void test200ImportLiveSyncTaskDummyBlue() throws Exception { final String TEST_NAME = "test200ImportLiveSyncTaskDummyBlue"; diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestLiveSyncTask.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestLiveSyncTask.java index d889bf9f428..ea2b5dcd990 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestLiveSyncTask.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestLiveSyncTask.java @@ -17,6 +17,7 @@ import java.io.FileNotFoundException; +import com.evolveum.midpoint.schema.constants.SchemaConstants; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; @@ -42,7 +43,11 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti dummyResourceGreen.setSyncStyle(DummySyncStyle.SMART); getDummyResource().setSyncStyle(DummySyncStyle.DUMB); getDummyResource(RESOURCE_DUMMY_BLUE_NAME).setSyncStyle(DummySyncStyle.SMART); + } + @Override + protected String getExpectedChannel() { + return SchemaConstants.CHANGE_CHANNEL_LIVE_SYNC_URI; } @Override diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestRecomputeTask.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestRecomputeTask.java index 2b678d2ec09..67fca16e923 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestRecomputeTask.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestRecomputeTask.java @@ -322,6 +322,7 @@ public void test120RecomputeByExpression() throws Exception { // GIVEN Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); + prepareNotifications(); // Preconditions assertUsers(6); @@ -367,6 +368,8 @@ public void test120RecomputeByExpression() throws Exception { assertUsers(6); + displayAllNotifications(); + assertSingleDummyTransportMessageContaining("simpleAccountNotifier-SUCCESS", "Channel: " + SchemaConstants.CHANGE_CHANNEL_RECOMPUTE_URI); } /** diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestReconTask.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestReconTask.java index c6f6261aaa6..7ccd725ed8f 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestReconTask.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/sync/TestReconTask.java @@ -17,6 +17,7 @@ import java.io.FileNotFoundException; +import com.evolveum.midpoint.schema.constants.SchemaConstants; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; @@ -52,6 +53,11 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti allwaysCheckTimestamp = true; } + @Override + protected String getExpectedChannel() { + return SchemaConstants.CHANGE_CHANNEL_RECON_URI; + } + @Override protected void importSyncTask(PrismObject resource) throws FileNotFoundException { if (resource == resourceDummyGreen) { diff --git a/model/model-intest/src/test/resources/notifications/system-configuration.xml b/model/model-intest/src/test/resources/notifications/system-configuration.xml index d3f05445de9..917e1ad1d86 100644 --- a/model/model-intest/src/test/resources/notifications/system-configuration.xml +++ b/model/model-intest/src/test/resources/notifications/system-configuration.xml @@ -236,6 +236,30 @@ Channel: $!event.channel sms:with-post + + customEvent + + + + + + from + + + +123 + +456 + +789 + + + body + + sms:with-post-multi + + target/mail-notifications.log @@ -271,5 +295,26 @@ Channel: $!event.channel target/sms.log + + + post + + + http://127.0.0.1:$$port$$/send + + + Content-Type: application/x-www-form-urlencoded + X-Custom: test + + + + + a9038321 + 5ecr3t + target/sms.log + + diff --git a/model/model-intest/src/test/resources/password/security-policy-default-storage-hashing.xml b/model/model-intest/src/test/resources/password/security-policy-default-storage-hashing.xml index 55dbc02dd45..444bcb2ea82 100644 --- a/model/model-intest/src/test/resources/password/security-policy-default-storage-hashing.xml +++ b/model/model-intest/src/test/resources/password/security-policy-default-storage-hashing.xml @@ -23,6 +23,9 @@ hashing + + hashing + diff --git a/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java b/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java index f7f0aec07a2..ab212109336 100644 --- a/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java +++ b/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java @@ -3419,13 +3419,15 @@ protected void checkDummyTransportMessages(String name, int expectedCount) { if (messages != null && !messages.isEmpty()) { LOGGER.error(messages.size() + " unexpected message(s) recorded in dummy transport '" + name + "'"); logNotifyMessages(messages); - assertFalse(messages.size() + " unexpected message(s) recorded in dummy transport '" + name + "'", true); + printNotifyMessages(messages); + fail(messages.size() + " unexpected message(s) recorded in dummy transport '" + name + "'"); } } else { assertNotNull("No messages recorded in dummy transport '" + name + "'", messages); if (expectedCount != messages.size()) { LOGGER.error("Invalid number of messages recorded in dummy transport '" + name + "', expected: "+expectedCount+", actual: "+messages.size()); logNotifyMessages(messages); + printNotifyMessages(messages); assertEquals("Invalid number of messages recorded in dummy transport '" + name + "'", expectedCount, messages.size()); } } @@ -3441,6 +3443,17 @@ protected void assertSingleDummyTransportMessage(String name, String expectedBod assertEquals("Unexpected notifier "+name+" message body", expectedBody, message.getBody()); } + protected void assertSingleDummyTransportMessageContaining(String name, String expectedSubstring) { + List messages = dummyTransport.getMessages("dummy:" + name); + assertNotNull("No messages recorded in dummy transport '" + name + "'", messages); + if (messages.size() != 1) { + fail("Invalid number of messages recorded in dummy transport '" + name + "', expected: 1, actual: "+messages.size()); + } + Message message = messages.get(0); + assertTrue("Notifier "+name+" message body does not contain text: " + expectedSubstring + ", it is:\n" + message.getBody(), + message.getBody().contains(expectedSubstring)); + } + protected String getDummyTransportMessageBody(String name, int index) { List messages = dummyTransport.getMessages("dummy:" + name); Message message = messages.get(index); @@ -3478,6 +3491,12 @@ private void logNotifyMessages(List messages) { } } + private void printNotifyMessages(List messages) { + for (Message message: messages) { + System.out.println(message); + } + } + protected void checkDummyTransportMessagesAtLeast(String name, int expectedCount) { if (expectedCount == 0) { return; diff --git a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/ModelEvent.java b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/ModelEvent.java index 3508e7d825f..566e29de140 100644 --- a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/ModelEvent.java +++ b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/ModelEvent.java @@ -149,6 +149,14 @@ public boolean isCategoryType(EventCategoryType eventCategoryType) { return eventCategoryType == EventCategoryType.MODEL_EVENT; } + public ObjectDelta getFocusPrimaryDelta() { + return getFocusContext() != null ? getFocusContext().getPrimaryDelta() : null; + } + + public ObjectDelta getFocusSecondaryDelta() { + return getFocusContext() != null ? getFocusContext().getSecondaryDelta() : null; + } + public List> getFocusDeltas() { List> retval = new ArrayList<>(); Class c = modelContext.getFocusClass(); diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/MailTransport.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/MailTransport.java index 9f404dc250c..297c9037384 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/MailTransport.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/MailTransport.java @@ -177,7 +177,7 @@ public void send(Message mailMessage, String transportName, Event event, Task ta LOGGER.debug("Using mail properties: "); for (Object key : properties.keySet()) { if (key instanceof String && ((String) key).startsWith("mail.")) { - LOGGER.debug(" - " + key + " = " + properties.get(key)); + LOGGER.debug(" - {} = {}", key, properties.get(key)); } } } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/SimpleSmsTransport.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/SimpleSmsTransport.java index fec669ba1e4..f9813847142 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/SimpleSmsTransport.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/SimpleSmsTransport.java @@ -75,6 +75,7 @@ import java.net.URI; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.stream.Collectors; @@ -174,11 +175,8 @@ public void send(Message message, String transportName, Event event, Task task, return; } - String to = message.getTo().get(0); - if (message.getTo().size() > 1) { - String msg = "Currently it is possible to send the SMS to one recipient only. Among " + message.getTo() + " the chosen one is " + to + " (the first one)."; - LOGGER.warn(msg) ; - } + List to = message.getTo(); + assert to.size() > 0; for (SmsGatewayConfigurationType smsGatewayConfigurationType : smsConfigurationType.getGateway()) { OperationResult resultForGateway = result.createSubresult(DOT_CLASS + "send.forGateway"); @@ -342,12 +340,18 @@ private List evaluateExpression(ExpressionType expressionType, Expressio return exprResult.getZeroSet().stream().map(ppv -> ppv.getValue()).collect(Collectors.toList()); } - protected ExpressionVariables getDefaultVariables(String from, String to, Message message) throws UnsupportedEncodingException { + protected ExpressionVariables getDefaultVariables(String from, List to, Message message) throws UnsupportedEncodingException { ExpressionVariables variables = new ExpressionVariables(); variables.addVariableDefinition(SchemaConstants.C_FROM, from); variables.addVariableDefinition(SchemaConstants.C_ENCODED_FROM, URLEncoder.encode(from, "US-ASCII")); - variables.addVariableDefinition(SchemaConstants.C_TO, to); - variables.addVariableDefinition(SchemaConstants.C_ENCODED_TO, URLEncoder.encode(to, "US-ASCII")); + variables.addVariableDefinition(SchemaConstants.C_TO, to.get(0)); + variables.addVariableDefinition(SchemaConstants.C_TO_LIST, to); + List encodedTo = new ArrayList<>(); + for (String s : to) { + encodedTo.add(URLEncoder.encode(s, "US-ASCII")); + } + variables.addVariableDefinition(SchemaConstants.C_ENCODED_TO, encodedTo.get(0)); + variables.addVariableDefinition(SchemaConstants.C_ENCODED_TO_LIST, encodedTo); variables.addVariableDefinition(SchemaConstants.C_MESSAGE_TEXT, message.getBody()); variables.addVariableDefinition(SchemaConstants.C_ENCODED_MESSAGE_TEXT, URLEncoder.encode(message.getBody(), "US-ASCII")); variables.addVariableDefinition(SchemaConstants.C_MESSAGE, message); diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/handlers/BaseHandler.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/handlers/BaseHandler.java index 12a23aac960..30ecac73e3e 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/handlers/BaseHandler.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/handlers/BaseHandler.java @@ -181,6 +181,7 @@ private List evaluateExpression(ExpressionType expressionType, Expressio QName resultName = new QName(SchemaConstants.NS_C, "result"); PrismPropertyDefinition resultDef = new PrismPropertyDefinitionImpl<>(resultName, DOMUtil.XSD_STRING, prismContext); + resultDef.setMaxOccurs(-1); Expression,PrismPropertyDefinition> expression = expressionFactory.makeExpression(expressionType, resultDef, shortDesc, task, result); ExpressionEvaluationContext params = new ExpressionEvaluationContext(null, expressionVariables, shortDesc, task, result); diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/UserPasswordNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/UserPasswordNotifier.java index ecd5a818b67..cd88e326ac3 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/UserPasswordNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/UserPasswordNotifier.java @@ -40,6 +40,8 @@ import java.util.List; +import static java.util.Collections.singletonList; + /** * @author mederly */ @@ -72,27 +74,52 @@ protected boolean quickCheckApplicability(Event event, GeneralNotifierType gener @Override protected boolean checkApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - if (!event.isSuccess()) { + if (!event.isAlsoSuccess()) { // TODO LOGGER.trace("Operation was not successful, exiting."); return false; } + return getPasswordFromEvent((ModelEvent) event) != null; // logging is done in the called method + } - ModelEvent modelEvent = (ModelEvent) event; + private String getPasswordFromEvent(ModelEvent modelEvent) { if (modelEvent.getFocusDeltas().isEmpty()) { LOGGER.trace("No user deltas in event, exiting."); - return false; + return null; } - if (getPasswordFromDeltas(modelEvent.getFocusDeltas()) != null) { - LOGGER.trace("Found password in user delta(s), continuing."); - return true; - } else { - LOGGER.trace("No password in user delta(s), exiting."); - return false; + String password = getPasswordFromDeltas(modelEvent.getFocusDeltas()); + if (password != null) { + LOGGER.trace("Found password in user executed delta(s), continuing."); + return password; } + //noinspection unchecked + ObjectDelta focusPrimaryDelta = (ObjectDelta) modelEvent.getFocusPrimaryDelta(); + //noinspection unchecked + ObjectDelta focusSecondaryDelta = (ObjectDelta) modelEvent.getFocusSecondaryDelta(); + if (focusPrimaryDelta == null && focusSecondaryDelta == null) { + LOGGER.trace("No password in executed delta(s) and no primary/secondary deltas, exiting."); + return null; + } + if (focusPrimaryDelta != null) { + password = getPasswordFromDeltas(singletonList(focusPrimaryDelta)); + if (password != null) { + LOGGER.trace("Found password in user primary delta, continuing."); + return password; + } + } + if (focusSecondaryDelta != null) { + password = getPasswordFromDeltas(singletonList(focusSecondaryDelta)); + if (password != null) { + LOGGER.trace("Found password in user secondary delta(s), continuing."); + return password; + } + } + LOGGER.trace("No password in executed delta(s) nor in primary/secondary deltas, exiting."); + return null; } private String getPasswordFromDeltas(List> deltas) { try { + //noinspection unchecked return midpointFunctions.getPlaintextUserPasswordFromDeltas((List) deltas); } catch (EncryptionException e) { LoggingUtils.logException(LOGGER, "Couldn't decrypt password from user deltas: {}", e, DebugUtil.debugDump(deltas)); @@ -107,15 +134,12 @@ protected String getSubject(Event event, GeneralNotifierType generalNotifierType @Override protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { - - ModelEvent modelEvent = (ModelEvent) event; - List> deltas = modelEvent.getFocusDeltas(); - return "Password for user " + notificationsUtil.getObjectType(event.getRequestee(), false, result).getName() + " is: " + getPasswordFromDeltas(deltas); + return "Password for user " + notificationsUtil.getObjectType(event.getRequestee(), false, result).getName() + + " is: " + getPasswordFromEvent((ModelEvent) event); } @Override protected Trace getLogger() { return LOGGER; } - } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/dao/ProcessInstanceManager.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/dao/ProcessInstanceManager.java index 4c1034d3640..d089b2d2a94 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/dao/ProcessInstanceManager.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/dao/ProcessInstanceManager.java @@ -119,7 +119,7 @@ public void onTaskDelete(Task task, OperationResult result) { } } - class Statistics { + static class Statistics { int processes = 0; int processesWithNonExistingTaskOid = 0; int processesWithNonWorkflowTaskOid = 0; diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/dao/WorkItemProvider.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/dao/WorkItemProvider.java index 2cd1cc22f74..c896629b175 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/dao/WorkItemProvider.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/dao/WorkItemProvider.java @@ -249,7 +249,7 @@ public List getMidpointAssignees(TaskExtract taskExtract) { /** * Helper class to carry relevant data from both Task and DelegateTask (to avoid code duplication) */ - private class TaskExtract { + private static class TaskExtract { private String id; private String assignee; diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/common/WfStageComputeHelper.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/common/WfStageComputeHelper.java index dc69413aca8..befb31f7dc8 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/common/WfStageComputeHelper.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/common/WfStageComputeHelper.java @@ -108,7 +108,7 @@ public ExpressionVariables getDefaultVariables(WfContextType wfContext, String r } // TODO name - public class ComputationResult { + public static class ComputationResult { private ApprovalLevelOutcomeType predeterminedOutcome; private AutomatedCompletionReasonType automatedCompletionReason; private Set approverRefs; diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseModelInvocationProcessingHelper.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseModelInvocationProcessingHelper.java index da62c6b3cd4..2cffa19278f 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseModelInvocationProcessingHelper.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseModelInvocationProcessingHelper.java @@ -150,17 +150,27 @@ private LocalizableMessage determineRootTaskName(ModelContext context) { */ private Task determineParentTaskForRoot(Task taskFromModel) { - // this is important: if existing task which we have got from model is transient (this is usual case), we create our root task as a task without parent! - // however, if the existing task is persistent (perhaps because the model operation executes already in the context of a workflow), we create a subtask - // todo think heavily about this; there might be a problem if a transient task from model gets (in the future) persistent - // -- in that case, it would not wait for its workflow-related children (but that's its problem, because children could finish even before - // that task is switched to background) +// // this is important: if existing task which we have got from model is transient (this is usual case), we create our root task as a task without parent! +// // however, if the existing task is persistent (perhaps because the model operation executes already in the context of a workflow), we create a subtask +// // todo think heavily about this; there might be a problem if a transient task from model gets (in the future) persistent +// // -- in that case, it would not wait for its workflow-related children (but that's its problem, because children could finish even before +// // that task is switched to background) +// +// if (taskFromModel.isTransient()) { +// return null; +// } else { +// return taskFromModel; +// } - if (taskFromModel.isTransient()) { - return null; - } else { - return taskFromModel; - } + /* + * Let us create all approval tasks as independent ones. This might resolve more issues, for example: + * - workflow tasks will be displayed on user Tasks tab (MID-4508): currently some of them are not, as they are technically subtasks + * - background tasks that initiate approvals (e.g. live sync or reconciliation) could end up with lots of subtasks, + * which makes their displaying take extraordinarily long + * + * It is to be seen if this will have some negative consequences. + */ + return null; } /** diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PolicyRuleApplication.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PolicyRuleApplication.java index eab1706e917..4ec696b5dc7 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PolicyRuleApplication.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PolicyRuleApplication.java @@ -31,7 +31,7 @@ */ public class PolicyRuleApplication { - class Cause { + static class Cause { private final ResourceShadowDiscriminator shadowDiscriminator; // non-null for projection context @NotNull private final ItemPath itemPath; // should be non-empty @NotNull private final PrismValue itemValue; diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/WfPropagateTaskObjectReferenceTaskHandler.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/WfPropagateTaskObjectReferenceTaskHandler.java index eb155492e6a..015adec87e2 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/WfPropagateTaskObjectReferenceTaskHandler.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/WfPropagateTaskObjectReferenceTaskHandler.java @@ -112,7 +112,7 @@ public TaskRunResult run(Task task) { ObjectReferenceType objectReferenceType = new ObjectReferenceType(); objectReferenceType.setType(type); objectReferenceType.setOid(oid); - + // TODO set also targetName [but it seems that this task handler is not used anymore] if (task.getObjectRef() == null) { task.setObjectRef(objectReferenceType); } else { @@ -123,9 +123,7 @@ public TaskRunResult run(Task task) { try { dependents = wfTask.listDependents(result); dependents.add(wfTask.getParentJob(result)); - } catch (SchemaException e) { - return reportException("Couldn't get dependents from job " + wfTask, task, result, e); - } catch (ObjectNotFoundException e) { + } catch (SchemaException | ObjectNotFoundException e) { return reportException("Couldn't get dependents from job " + wfTask, task, result, e); } @@ -133,13 +131,9 @@ public TaskRunResult run(Task task) { if (dependent.getTask().getObjectRef() == null) { try { dependent.getTask().setObjectRefImmediate(objectReferenceType, result); - } catch (ObjectNotFoundException e) { + } catch (ObjectNotFoundException | SchemaException | ObjectAlreadyExistsException e) { // note we DO NOT return, because we want to set all references we can reportException("Couldn't set object reference on job " + dependent, task, result, e); - } catch (SchemaException e) { - reportException("Couldn't set object reference on job " + dependent, task, result, e); - } catch (ObjectAlreadyExistsException e) { - reportException("Couldn't set object reference on job " + dependent, task, result, e); } } else { LOGGER.warn("object reference in job " + dependent + " is already set, although it shouldn't be"); diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java index 7fe8701c60a..67c634fbcd4 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/ApprovalSchemaBuilder.java @@ -51,7 +51,7 @@ void setProcessSpecification(ProcessSpecification processSpecification) { this.processSpecification = processSpecification; } - class Result { + static class Result { @NotNull final ApprovalSchemaType schemaType; @NotNull final SchemaAttachedPolicyRulesType attachedRules; @Nullable final ProcessSpecification processSpecification; @@ -68,7 +68,7 @@ public Result(@NotNull ApprovalSchemaType schemaType, } } - private class Fragment { + private static class Fragment { // object to which relations (approved, owner) are resolved // TODO test this thoroughly in presence of non-direct rules and merged schemas final PrismObject target; diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/tasks/WfTaskController.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/tasks/WfTaskController.java index 94847998d34..4ae0412a90d 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/tasks/WfTaskController.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/tasks/WfTaskController.java @@ -117,9 +117,7 @@ public WfTask submitWfTask(WfTaskCreationInstruction instruction, WfTask parentW */ public WfTask submitWfTask(WfTaskCreationInstruction instruction, Task parentTask, WfConfigurationType wfConfigurationType, String channelOverride, OperationResult result) throws SchemaException, ObjectNotFoundException { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Processing start instruction:\n{}", instruction.debugDump()); - } + LOGGER.trace("Processing start instruction:\n{}", instruction.debugDumpLazily()); Task task = submitTask(instruction, parentTask, wfConfigurationType, channelOverride, result); WfTask wfTask = recreateWfTask(task, instruction.getChangeProcessor()); if (!instruction.isNoProcess()) { diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/tasks/WfTaskCreationInstruction.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/tasks/WfTaskCreationInstruction.java index 53cc5d3bc35..17a4e520269 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/tasks/WfTaskCreationInstruction.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/tasks/WfTaskCreationInstruction.java @@ -372,7 +372,8 @@ public Task createTask(WfTaskController taskController, Task parentTask, WfConfi task.setCategory(TaskCategory.WORKFLOW); if (taskObject != null) { - task.setObjectRef(taskObject.getOid(), taskObject.getDefinition().getTypeName()); + //noinspection unchecked + task.setObjectRef(ObjectTypeUtil.createObjectRef(taskObject)); } else if (parentTask != null && parentTask.getObjectRef() != null) { task.setObjectRef(parentTask.getObjectRef().clone()); } diff --git a/pom.xml b/pom.xml index 9b1c36348ae..78fd80a20d6 100644 --- a/pom.xml +++ b/pom.xml @@ -82,6 +82,11 @@ maven-plugin-plugin 3.3 + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + org.eclipse.m2e lifecycle-mapping diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ConnectorManager.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ConnectorManager.java index 05a94ced7b6..e13f93564a2 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ConnectorManager.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ConnectorManager.java @@ -533,7 +533,7 @@ public String getFrameworkVersion() { return connectorFactory.getFrameworkVersion(); } - private class ConfiguredConnectorInstanceEntry { + private static class ConfiguredConnectorInstanceEntry { public String connectorOid; public PrismContainer configuration; public ConnectorInstance connectorInstance; diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowManager.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowManager.java index b836e9829c4..43e95b1b714 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowManager.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowManager.java @@ -23,6 +23,7 @@ import javax.xml.namespace.QName; +import com.evolveum.midpoint.util.QNameUtil; import org.apache.commons.lang.BooleanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -176,7 +177,7 @@ public ResourceOperationDescription createResourceFailureDescription( failureDesc.setObjectDelta(objectDelta); failureDesc.setResource(resource.asPrismObject()); failureDesc.setResult(parentResult); - failureDesc.setSourceChannel(SchemaConstants.CHANGE_CHANNEL_DISCOVERY.getLocalPart()); + failureDesc.setSourceChannel(QNameUtil.qNameToUri(SchemaConstants.CHANGE_CHANNEL_DISCOVERY)); return failureDesc; } diff --git a/provisioning/ucf-impl-builtin/src/main/java/com/evolveum/midpoint/provisioning/ucf/impl/builtin/ConnectorFactoryBuiltinImpl.java b/provisioning/ucf-impl-builtin/src/main/java/com/evolveum/midpoint/provisioning/ucf/impl/builtin/ConnectorFactoryBuiltinImpl.java index 6dea32f25fa..6677f4a3fd7 100644 --- a/provisioning/ucf-impl-builtin/src/main/java/com/evolveum/midpoint/provisioning/ucf/impl/builtin/ConnectorFactoryBuiltinImpl.java +++ b/provisioning/ucf-impl-builtin/src/main/java/com/evolveum/midpoint/provisioning/ucf/impl/builtin/ConnectorFactoryBuiltinImpl.java @@ -277,7 +277,7 @@ public void shutdown() { // Nothing to do } - private class ConnectorStruct { + private static class ConnectorStruct { Class connectorClass; ConnectorType connectorObject; PrismSchema connectorConfigurationSchema; diff --git a/provisioning/ucf-impl-connid/src/main/java/com/evolveum/midpoint/provisioning/ucf/impl/connid/ConnectorFactoryConnIdImpl.java b/provisioning/ucf-impl-connid/src/main/java/com/evolveum/midpoint/provisioning/ucf/impl/connid/ConnectorFactoryConnIdImpl.java index 05c8238b987..47e5e5df703 100644 --- a/provisioning/ucf-impl-connid/src/main/java/com/evolveum/midpoint/provisioning/ucf/impl/connid/ConnectorFactoryConnIdImpl.java +++ b/provisioning/ucf-impl-connid/src/main/java/com/evolveum/midpoint/provisioning/ucf/impl/connid/ConnectorFactoryConnIdImpl.java @@ -22,6 +22,7 @@ import java.io.InputStream; import java.lang.reflect.Field; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.security.Key; import java.util.Arrays; @@ -40,6 +41,7 @@ import javax.xml.namespace.QName; import com.evolveum.midpoint.prism.schema.PrismSchemaImpl; +import com.evolveum.midpoint.util.MiscUtil; import org.apache.commons.configuration.Configuration; import org.identityconnectors.common.Version; import org.identityconnectors.common.security.Encryptor; @@ -172,17 +174,12 @@ public class ConnectorFactoryConnIdImpl implements ConnectorFactory { private ConnectorInfoManagerFactory connectorInfoManagerFactory; private ConnectorInfoManager localConnectorInfoManager; - private Set bundleURLs; + private Set bundleURIs; private Set localConnectorTypes = null; - @Autowired(required = true) - private MidpointConfiguration midpointConfiguration; - - @Autowired(required = true) - private Protector protector; - - @Autowired(required = true) - private PrismContext prismContext; + @Autowired private MidpointConfiguration midpointConfiguration; + @Autowired private Protector protector; + @Autowired private PrismContext prismContext; public ConnectorFactoryConnIdImpl() { } @@ -195,26 +192,26 @@ public ConnectorFactoryConnIdImpl() { public void initialize() { // OLD - // bundleURLs = listBundleJars(); - bundleURLs = new HashSet<>(); + // bundleURIs = listBundleJars(); + bundleURIs = new HashSet<>(); Configuration config = midpointConfiguration.getConfiguration("midpoint.icf"); // Is classpath scan enabled if (config.getBoolean("scanClasspath")) { // Scan class path - bundleURLs.addAll(scanClassPathForBundles()); + bundleURIs.addAll(scanClassPathForBundles()); } // Scan all provided directories @SuppressWarnings("unchecked") List dirs = config.getList("scanDirectory"); for (String dir : dirs) { - bundleURLs.addAll(scanDirectory(dir)); + bundleURIs.addAll(scanDirectory(dir)); } - for (URL u : bundleURLs) { - LOGGER.debug("ICF bundle URL : {}", u); + for (URI u : bundleURIs) { + LOGGER.debug("ICF bundle URI : {}", u); } connectorInfoManagerFactory = ConnectorInfoManagerFactory.getInstance(); @@ -501,9 +498,11 @@ private PrismSchema generateConnectorConfigurationSchema(ConnectorInfo cinfo, Co * * @return ICF connector info manager that manages local connectors */ + private ConnectorInfoManager getLocalConnectorInfoManager() { if (null == localConnectorInfoManager) { - localConnectorInfoManager = connectorInfoManagerFactory.getLocalManager(bundleURLs.toArray(new URL[0])); + URL[] urls = bundleURIs.stream().map(MiscUtil::toUrlUnchecked).toArray(URL[]::new); + localConnectorInfoManager = connectorInfoManagerFactory.getLocalManager(urls); } return localConnectorInfoManager; } @@ -543,8 +542,8 @@ private ConnectorInfoManager getRemoteConnectorInfoManager(ConnectorHostType hos * * @return Set of all bundle URL */ - private Set scanClassPathForBundles() { - Set bundle = new HashSet<>(); + private Set scanClassPathForBundles() { + Set bundle = new HashSet<>(); // scan class path for bundles Enumeration en = null; @@ -595,7 +594,11 @@ private Set scanClassPathForBundles() { URL tmp = new URL(toUrl(upath.substring(0, upath.lastIndexOf("!")))); if (isThisBundleCompatible(tmp)) { - bundle.add(tmp); + try { + bundle.add(tmp.toURI()); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } } else { LOGGER.warn("Skip loading ICF bundle {} due error occured", tmp); } @@ -623,23 +626,24 @@ private String toUrl(String string) { * @param path * @return */ - private Set scanDirectory(String path) { + private Set scanDirectory(String path) { // Prepare return object - Set bundle = new HashSet<>(); - // COnvert path to object File + Set bundle = new HashSet<>(); + // Convert path to object File File dir = new File(path); // Test if this path is single jar or need to do deep examination if (isThisJarFileBundle(dir)) { try { - if (isThisBundleCompatible(dir.toURI().toURL())) { - bundle.add(dir.toURI().toURL()); + final URI uri = dir.toURI(); + if (isThisBundleCompatible(uri.toURL())) { + bundle.add(uri); } else { - LOGGER.warn("Skip loading budle {} due error occured", dir.toURI().toURL()); + LOGGER.warn("Skip loading bundle {} due error occurred", uri.toURL()); } } catch (MalformedURLException e) { - LOGGER.error("This never happend we hope.", e); + LOGGER.error("This never happened we hope.", e); throw new SystemException(e); } return bundle; @@ -657,17 +661,18 @@ private Set scanDirectory(String path) { return bundle; } - // test all entires for bundle + // test all entries for bundle for (int i = 0; i < dirEntries.length; i++) { if (isThisJarFileBundle(dirEntries[i])) { try { - if (isThisBundleCompatible(dirEntries[i].toURI().toURL())) { - bundle.add(dirEntries[i].toURI().toURL()); + final URI uri = dirEntries[i].toURI(); + if (isThisBundleCompatible(uri.toURL())) { + bundle.add(uri); } else { - LOGGER.warn("Skip loading budle {} due error occured", dirEntries[i].toURI().toURL()); + LOGGER.warn("Skip loading bundle {} due error occurred", uri.toURL()); } } catch (MalformedURLException e) { - LOGGER.error("This never happend we hope.", e); + LOGGER.error("This never happened we hope.", e); throw new SystemException(e); } } diff --git a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/task/AbstractSearchIterativeTaskHandler.java b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/task/AbstractSearchIterativeTaskHandler.java index b53bdd6d8aa..6b77c8f00f3 100644 --- a/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/task/AbstractSearchIterativeTaskHandler.java +++ b/repo/repo-common/src/main/java/com/evolveum/midpoint/repo/common/task/AbstractSearchIterativeTaskHandler.java @@ -17,16 +17,14 @@ import static com.evolveum.midpoint.prism.PrismProperty.getRealValue; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import java.util.function.Function; import javax.xml.namespace.QName; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.schema.util.MiscSchemaUtil; import com.evolveum.midpoint.schema.util.TaskWorkStateTypeUtil; import com.evolveum.midpoint.task.api.*; import com.evolveum.midpoint.util.exception.*; @@ -194,6 +192,13 @@ public TaskWorkBucketProcessingResult run(Task localCoordinatorTask, WorkBucketT OperationResult opResult = runResult.getOperationResult(); opResult.setStatus(OperationResultStatus.IN_PROGRESS); + if (localCoordinatorTask.getChannel() == null) { + String channel = getDefaultChannel(); + if (channel != null) { + localCoordinatorTask.setChannel(channel); + } + } + try { H resultHandler = setupHandler(runResult, localCoordinatorTask, opResult); @@ -312,6 +317,10 @@ public TaskWorkBucketProcessingResult run(Task localCoordinatorTask, WorkBucketT } } + protected String getDefaultChannel() { + return null; + } + private Collection> updateSearchOptionsWithIterationMethod( Collection> searchOptions, Task localCoordinatorTask) { Collection> rv; @@ -490,10 +499,10 @@ protected ObjectQuery createQuery(H handler, TaskRunResult runResult, Task coord // useful e.g. to specify noFetch options for shadow-related queries protected Collection> createSearchOptions(H resultHandler, TaskRunResult runResult, Task coordinatorTask, OperationResult opResult) { - return null; + return createSearchOptionsFromTask(resultHandler, runResult, coordinatorTask, opResult); } - // as provisioning service does not allow searches without specifying resource or objectclass/kind, we need to be able to contact repository directly + // as provisioning service does not allow searches without specifying resource or objectclass/kind, we need to be able to contact repository directly // for some specific tasks protected boolean useRepositoryDirectly(H resultHandler, TaskRunResult runResult, Task coordinatorTask, OperationResult opResult) { return false; @@ -522,7 +531,13 @@ protected ObjectQuery createQueryFromTask(H handler, TaskRunResult runResult, Ta return query != null ? query : new ObjectQuery(); } - protected ObjectQuery createQueryFromTaskIfExists(H handler, TaskRunResult runResult, Task task, OperationResult opResult) throws SchemaException { + protected Collection> createSearchOptionsFromTask(H resultHandler, TaskRunResult runResult, + Task coordinatorTask, OperationResult opResult) { + SelectorQualifiedGetOptionsType opts = getRealValue(coordinatorTask.getExtensionProperty(SchemaConstants.MODEL_EXTENSION_SEARCH_OPTIONS)); + return MiscSchemaUtil.optionsTypeToOptions(opts); + } + + protected ObjectQuery createQueryFromTaskIfExists(H handler, TaskRunResult runResult, Task task, OperationResult opResult) throws SchemaException { Class objectType = getType(task); LOGGER.trace("Object type = {}", objectType); diff --git a/repo/repo-sql-impl-test/src/main/java/com/evolveum/midpoint/repo/sql/testing/TestSqlRepositoryFactory.java b/repo/repo-sql-impl-test/src/main/java/com/evolveum/midpoint/repo/sql/testing/TestSqlRepositoryFactory.java index dd0c8c425b4..83b815bfb46 100644 --- a/repo/repo-sql-impl-test/src/main/java/com/evolveum/midpoint/repo/sql/testing/TestSqlRepositoryFactory.java +++ b/repo/repo-sql-impl-test/src/main/java/com/evolveum/midpoint/repo/sql/testing/TestSqlRepositoryFactory.java @@ -148,7 +148,7 @@ private void updateConfigurationBooleanProperty(Configuration configuration, Pro if (value == null) { return; } - boolean val = new Boolean(value).booleanValue(); + boolean val = Boolean.valueOf(value); LOGGER.info("Overriding loaded configuration with value read from system properties: {}={}", propertyName, val); configuration.setProperty(propertyName, val); } diff --git a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AddGetObjectTest.java b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AddGetObjectTest.java index f1bfbcf9854..9d11a0ca208 100644 --- a/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AddGetObjectTest.java +++ b/repo/repo-sql-impl-test/src/test/java/com/evolveum/midpoint/repo/sql/AddGetObjectTest.java @@ -22,6 +22,7 @@ import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.ReferenceDelta; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.repo.api.RepoAddOptions; import com.evolveum.midpoint.repo.sql.type.XMLGregorianCalendarType; @@ -126,10 +127,22 @@ public void addGetDSEESyncDoubleTest() throws Exception { public void simpleAddGetTest() throws Exception { LOGGER.info("===[ simpleAddGetTest ]==="); final File OBJECTS_FILE = new File(FOLDER_BASIC, "objects.xml"); - addGetCompare(OBJECTS_FILE); + List> objects = addGetCompare(OBJECTS_FILE); + + boolean foundAtestuserX00003 = false; + for (PrismObject object : objects) { + // adhoc check whether reference.targetName is preserved + if ("atestuserX00003".equals(PolyString.getOrig(object.getName()))) { + String personaName = PolyString.getOrig(((UserType) object.asObjectable()).getPersonaRef().get(0).getTargetName()); + assertEquals("Wrong personaRef.targetName on atestuserX00003", null, personaName); + foundAtestuserX00003 = true; + break; + } + } + assertTrue("User atestuserX00003 was not found", foundAtestuserX00003); } - private void addGetCompare(File file) throws Exception { + private List> addGetCompare(File file) throws Exception { List> elements = prismContext.parserFor(file).parseObjects(); List oids = new ArrayList<>(); @@ -141,9 +154,9 @@ private void addGetCompare(File file) throws Exception { object.getCompileTimeClass().getSimpleName()}); oids.add(repositoryService.addObject(object, null, result)); } - LOGGER.info("Time to add objects ({}): {}", new Object[]{elements.size(), - (System.currentTimeMillis() - time),}); + LOGGER.info("Time to add objects ({}): {}", elements.size(), System.currentTimeMillis() - time); + List> objectsRead = new ArrayList<>(); int count = 0; elements = prismContext.parserFor(file).parseObjects(); for (int i = 0; i < elements.size(); i++) { @@ -171,10 +184,8 @@ private void addGetCompare(File file) throws Exception { System.out.println("OLD: " + object.findProperty(ObjectType.F_NAME).getValue()); System.out.println("NEW: " + newObject.findProperty(ObjectType.F_NAME).getValue()); + objectsRead.add(newObject); ObjectDelta delta = object.diff(newObject); - if (delta == null) { - continue; - } count += delta.getModifications().size(); if (delta.getModifications().size() > 0) { @@ -186,8 +197,8 @@ private void addGetCompare(File file) throws Exception { continue; } } - LOGGER.error(">>> {} Found {} changes for {}\n{}", new Object[]{(i + 1), - delta.getModifications().size(), newObject.toString(), delta.debugDump(3)}); + LOGGER.error(">>> {} Found {} changes for {}\n{}", (i + 1), + delta.getModifications().size(), newObject.toString(), delta.debugDump(3)); ItemDelta id = (ItemDelta) delta.getModifications().iterator().next(); if (id.isReplace()) { LOGGER.debug("{}", id.getValuesToReplace().iterator().next()); @@ -199,8 +210,8 @@ private void addGetCompare(File file) throws Exception { throw new RuntimeException("Exception during processing of "+object+": "+ex.getMessage(), ex); } } - AssertJUnit.assertEquals("Found changes during add/get test " + count, 0, count); + return objectsRead; } private Integer size(PrismContainerValue value) { diff --git a/repo/repo-sql-impl-test/src/test/resources/basic/objects.xml b/repo/repo-sql-impl-test/src/test/resources/basic/objects.xml index b29cc9482fc..68369d8b5d9 100644 --- a/repo/repo-sql-impl-test/src/test/resources/basic/objects.xml +++ b/repo/repo-sql-impl-test/src/test/resources/basic/objects.xml @@ -164,7 +164,7 @@ - + u-000 Test UserX00003 diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlPerformanceMonitor.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlPerformanceMonitor.java index 1e6e63c48b9..a98a3c3325d 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlPerformanceMonitor.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlPerformanceMonitor.java @@ -51,7 +51,7 @@ public class SqlPerformanceMonitor { private SqlRepositoryFactory sqlRepositoryFactory; - class OperationRecord { + static class OperationRecord { String kind; long handle; int attempts; @@ -121,7 +121,7 @@ private void writeStatisticsToFile(String file) { } - class StatEntry { + static class StatEntry { long totalTime, wastedTime; int attempts; int records; diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java index 48f7b774339..5e56401e7ff 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/helpers/ObjectUpdater.java @@ -16,10 +16,7 @@ package com.evolveum.midpoint.repo.sql.helpers; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectDefinition; -import com.evolveum.midpoint.prism.PrismReference; +import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.ReferenceDelta; @@ -263,7 +260,7 @@ public void updateFullObject(RObject object, PrismObject< // Its' because we're removing some properties during save operation and if save fails, // overwrite attempt (for example using object importer) might try to delete existing object // and then try to save this object one more time. - String xml = prismContext.serializeObjectToString(savedObject, PrismContext.LANG_XML); + String xml = prismContext.xmlSerializer().serialize(savedObject); savedObject = prismContext.parseObject(xml); if (FocusType.class.isAssignableFrom(savedObject.getCompileTimeClass())) { @@ -274,7 +271,7 @@ public void updateFullObject(RObject object, PrismObject< savedObject.removeContainer(AccessCertificationCampaignType.F_CASE); } - xml = prismContext.serializeObjectToString(savedObject, PrismContext.LANG_XML); + xml = prismContext.xmlSerializer().serialize(savedObject); byte[] fullObject = RUtil.getByteArrayFromXml(xml, getConfiguration().isUseZip()); LOGGER.trace("Storing full object\n{}", xml); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java index 242671d38a1..9496e325322 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/query2/hqm/HibernateQuery.java @@ -58,7 +58,7 @@ public abstract class HibernateQuery { */ private List conditions = new ArrayList<>(); - public class Ordering { + public static class Ordering { @NotNull private final String byProperty; private final OrderDirection direction; @@ -80,7 +80,7 @@ public OrderDirection getDirection() { private List orderingList = new ArrayList<>(); - public class Grouping { + public static class Grouping { @NotNull private final String byProperty; Grouping(@NotNull String byProperty) { diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskManagerConfiguration.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskManagerConfiguration.java index a927d531afd..89434145560 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskManagerConfiguration.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskManagerConfiguration.java @@ -75,6 +75,11 @@ public class TaskManagerConfiguration { private static final String RUN_NOW_KEEPS_ORIGINAL_SCHEDULE_CONFIG_ENTRY = "runNowKeepsOriginalSchedule"; private static final String SCHEDULER_INITIALLY_STOPPED_CONFIG_ENTRY = "schedulerInitiallyStopped"; + private static final String WORK_ALLOCATION_MAX_ATTEMPTS_ENTRY = "workAllocationMaxAttempts"; + private static final String WORK_ALLOCATION_RETRY_INTERVAL_ENTRY = "workAllocationRetryInterval"; + private static final String WORK_ALLOCATION_INITIAL_DELAY_ENTRY = "workAllocationInitialDelay"; + private static final String WORK_ALLOCATION_DEFAULT_FREE_BUCKET_WAIT_INTERVAL_ENTRY = "workAllocationDefaultFreeBucketWaitInterval"; + private static final String MIDPOINT_NODE_ID_PROPERTY = "midpoint.nodeId"; private static final String MIDPOINT_JMX_HOST_NAME_PROPERTY = "midpoint.jmxHostName"; private static final String JMX_PORT_PROPERTY = "com.sun.management.jmxremote.port"; @@ -99,6 +104,11 @@ public class TaskManagerConfiguration { private static final int STALLED_TASKS_REPEATED_NOTIFICATION_INTERVAL_DEFAULT = 3600; private static final boolean RUN_NOW_KEEPS_ORIGINAL_SCHEDULE_DEFAULT = false; + private static final int WORK_ALLOCATION_MAX_ATTEMPTS_DEFAULT = 40; + private static final long WORK_ALLOCATION_RETRY_INTERVAL_DEFAULT = 5000L; + private static final long WORK_ALLOCATION_INITIAL_DELAY_DEFAULT = 5000L; + private static final long WORK_ALLOCATION_DEFAULT_FREE_BUCKET_WAIT_INTERVAL_DEFAULT = 20000L; + private boolean stopOnInitializationFailure; private int threads; private boolean jdbcJobStore; @@ -117,6 +127,11 @@ public class TaskManagerConfiguration { private boolean runNowKeepsOriginalSchedule; private boolean schedulerInitiallyStopped; + private int workAllocationMaxAttempts; + private long workAllocationRetryInterval; + private long workAllocationInitialDelay; + private long workAllocationDefaultFreeBucketWaitInterval; + // JMX credentials for connecting to remote nodes private String jmxUsername; private String jmxPassword; @@ -178,7 +193,11 @@ public class TaskManagerConfiguration { STALLED_TASKS_THRESHOLD_CONFIG_ENTRY, STALLED_TASKS_REPEATED_NOTIFICATION_INTERVAL_CONFIG_ENTRY, RUN_NOW_KEEPS_ORIGINAL_SCHEDULE_CONFIG_ENTRY, - SCHEDULER_INITIALLY_STOPPED_CONFIG_ENTRY + SCHEDULER_INITIALLY_STOPPED_CONFIG_ENTRY, + WORK_ALLOCATION_MAX_ATTEMPTS_ENTRY, + WORK_ALLOCATION_RETRY_INTERVAL_ENTRY, + WORK_ALLOCATION_INITIAL_DELAY_ENTRY, + WORK_ALLOCATION_DEFAULT_FREE_BUCKET_WAIT_INTERVAL_ENTRY ); void checkAllowedKeys(MidpointConfiguration masterConfig) throws TaskManagerConfigurationException { @@ -269,6 +288,12 @@ void setBasicInformation(MidpointConfiguration masterConfig) throws TaskManagerC stalledTasksRepeatedNotificationInterval = c.getInt(STALLED_TASKS_REPEATED_NOTIFICATION_INTERVAL_CONFIG_ENTRY, STALLED_TASKS_REPEATED_NOTIFICATION_INTERVAL_DEFAULT); runNowKeepsOriginalSchedule = c.getBoolean(RUN_NOW_KEEPS_ORIGINAL_SCHEDULE_CONFIG_ENTRY, RUN_NOW_KEEPS_ORIGINAL_SCHEDULE_DEFAULT); schedulerInitiallyStopped = c.getBoolean(SCHEDULER_INITIALLY_STOPPED_CONFIG_ENTRY, false); + + workAllocationMaxAttempts = c.getInt(WORK_ALLOCATION_MAX_ATTEMPTS_ENTRY, WORK_ALLOCATION_MAX_ATTEMPTS_DEFAULT); + workAllocationRetryInterval = c.getLong(WORK_ALLOCATION_RETRY_INTERVAL_ENTRY, WORK_ALLOCATION_RETRY_INTERVAL_DEFAULT); + workAllocationInitialDelay = c.getLong(WORK_ALLOCATION_INITIAL_DELAY_ENTRY, WORK_ALLOCATION_INITIAL_DELAY_DEFAULT); + workAllocationDefaultFreeBucketWaitInterval = c.getLong(WORK_ALLOCATION_DEFAULT_FREE_BUCKET_WAIT_INTERVAL_ENTRY, + WORK_ALLOCATION_DEFAULT_FREE_BUCKET_WAIT_INTERVAL_DEFAULT); } private static final Map schemas = new HashMap<>(); @@ -339,8 +364,6 @@ void setJdbcJobStoreInformation(MidpointConfiguration masterConfig, SqlRepositor /** * Check configuration, except for JDBC JobStore-specific parts. - * - * @throws TaskManagerConfigurationException */ void validateBasicInformation() throws TaskManagerConfigurationException { @@ -525,4 +548,20 @@ public String getDataSource() { public boolean isSchedulerInitiallyStopped() { return schedulerInitiallyStopped; } + + public int getWorkAllocationMaxAttempts() { + return workAllocationMaxAttempts; + } + + public long getWorkAllocationRetryInterval() { + return workAllocationRetryInterval; + } + + public long getWorkAllocationInitialDelay() { + return workAllocationInitialDelay; + } + + public long getWorkAllocationDefaultFreeBucketWaitInterval() { + return workAllocationDefaultFreeBucketWaitInterval; + } } diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskManagerQuartzImpl.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskManagerQuartzImpl.java index 894225fe840..48c15b6b051 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskManagerQuartzImpl.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskManagerQuartzImpl.java @@ -2141,6 +2141,6 @@ public TaskHandler createAndRegisterPartitioningTaskHandler(String handlerUri, F @Override public void setFreeBucketWaitInterval(long value) { - workStateManager.setFreeBucketWaitInterval(value); + workStateManager.setFreeBucketWaitIntervalOverride(value); } } diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskQuartzImpl.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskQuartzImpl.java index 0804dd42bc5..9b6723bd058 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskQuartzImpl.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskQuartzImpl.java @@ -1547,26 +1547,13 @@ public void setObjectRefImmediate(ObjectReferenceType value, OperationResult par } public void setObjectRefTransient(ObjectReferenceType objectRefType) { - PrismReference objectRef; - try { - objectRef = taskPrism.findOrCreateReference(TaskType.F_OBJECT_REF); - } catch (SchemaException e) { - // This should not happen - throw new IllegalStateException("Internal schema error: " + e.getMessage(), e); - } - objectRef.getValue().setOid(objectRefType.getOid()); - objectRef.getValue().setTargetType(objectRefType.getType()); + taskPrism.asObjectable().setObjectRef(objectRefType != null ? objectRefType.clone() : null); } private ReferenceDelta setObjectRefAndPrepareDelta(ObjectReferenceType value) { setObjectRefTransient(value); - - PrismReferenceValue prismReferenceValue = new PrismReferenceValue(); - prismReferenceValue.setOid(value.getOid()); - prismReferenceValue.setTargetType(value.getType()); - return isPersistent() ? ReferenceDelta.createModificationReplace(TaskType.F_OBJECT_REF, - taskManager.getTaskObjectDefinition(), prismReferenceValue) : null; + taskManager.getTaskObjectDefinition(), value.clone().asReferenceValue()) : null; } @Override diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/execution/JobExecutor.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/execution/JobExecutor.java index 6eed5dd1f15..a4b56426a1b 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/execution/JobExecutor.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/execution/JobExecutor.java @@ -216,7 +216,7 @@ public void execute(JobExecutionContext context) throws JobExecutionException { } - class GroupExecInfo { + static class GroupExecInfo { int limit; Set tasks = new HashSet<>(); @@ -314,7 +314,7 @@ private void addToGroupMap(Map groupMap, Task otherTask) } } - private class RescheduleTime { + private static class RescheduleTime { private final long timestamp; private final boolean regular; private RescheduleTime(long timestamp, boolean regular) { @@ -689,6 +689,12 @@ private TaskRunResult executeWorkBucketAwareTaskHandler(WorkBucketAwareTaskHandl } } + try { + workStateManager.executeInitialDelay(task); + } catch (InterruptedException e) { + return createInterruptedTaskRunResult(); + } + TaskWorkBucketProcessingResult runResult = null; for (;;) { WorkBucketType bucket; diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/handlers/JdbcPingTaskHandler.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/handlers/JdbcPingTaskHandler.java index 88e99e72eca..88ef16de576 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/handlers/JdbcPingTaskHandler.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/handlers/JdbcPingTaskHandler.java @@ -55,7 +55,7 @@ public void initialize() { taskManager.registerHandler(HANDLER_URI, this); } - private class Statistics { + private static class Statistics { Integer min = null; Integer max = null; int total = 0; diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/work/WorkStateManager.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/work/WorkStateManager.java index b00ac72553d..6fc6ee7915b 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/work/WorkStateManager.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/work/WorkStateManager.java @@ -34,6 +34,9 @@ import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.task.api.TaskExecutionStatus; import com.evolveum.midpoint.task.api.TaskManager; +import com.evolveum.midpoint.task.quartzimpl.TaskManagerConfiguration; +import com.evolveum.midpoint.task.quartzimpl.TaskManagerQuartzImpl; +import com.evolveum.midpoint.task.quartzimpl.TaskQuartzImpl; import com.evolveum.midpoint.task.quartzimpl.work.segmentation.content.WorkBucketContentHandler; import com.evolveum.midpoint.task.quartzimpl.work.segmentation.content.WorkBucketContentHandlerRegistry; import com.evolveum.midpoint.task.quartzimpl.work.segmentation.WorkSegmentationStrategy; @@ -81,12 +84,9 @@ public class WorkStateManager { @Autowired private WorkSegmentationStrategyFactory strategyFactory; @Autowired private WorkBucketContentHandlerRegistry handlerFactory; - private static final int MAX_ATTEMPTS = 40; // temporary - private static final long DELAY_INTERVAL = 5000L; // temporary - private static final long DEFAULT_FREE_BUCKET_WAIT_INTERVAL = 20000L; private static final long DYNAMIC_SLEEP_INTERVAL = 100L; - private long freeBucketWaitInterval = DEFAULT_FREE_BUCKET_WAIT_INTERVAL; + private Long freeBucketWaitIntervalOverride = null; private class Context { Task workerTask; @@ -113,15 +113,15 @@ public void reloadWorkerTask(OperationResult result) throws SchemaException, Obj workerTask = taskManager.getTask(workerTask.getOid(), null, result); } - public boolean canRun() { - return canRunSupplier == null || BooleanUtils.isTrue(canRunSupplier.get()); - } - public TaskWorkManagementType getWorkStateConfiguration() { return isStandalone() ? workerTask.getWorkManagement() : coordinatorTask.getWorkManagement(); } } + public boolean canRun(Supplier canRunSupplier) { + return canRunSupplier == null || BooleanUtils.isTrue(canRunSupplier.get()); + } + /** * Allocates work bucket. If no free work buckets are currently present it tries to create one. * If there is already allocated work bucket for given worker task, it is returned. @@ -172,8 +172,8 @@ private WorkBucketType getWorkBucketMultiNode(Context ctx, long freeBucketWaitTi waitForAvailableBucket: // this cycle exits when something is found OR when a definite 'no more buckets' answer is received for (;;) { -waitForConflictLessUpdate: // this cycle exits when coordinator task update succeeds - for (int attempt = 0; attempt < MAX_ATTEMPTS; attempt++) { + waitForConflictLessUpdate: // this cycle exits when coordinator task update succeeds + for (int attempt = 0; attempt < getMaxAttempts(); attempt++) { TaskWorkStateType coordinatorWorkState = getWorkStateOrNew(ctx.coordinatorTask.getTaskPrismObject()); GetBucketResult response = workStateStrategy.getBucket(coordinatorWorkState); LOGGER.trace("getWorkBucketMultiNode: workStateStrategy returned {} for worker task {}, coordinator {}", response, ctx.workerTask, ctx.coordinatorTask); @@ -215,7 +215,7 @@ private WorkBucketType getWorkBucketMultiNode(Context ctx, long freeBucketWaitTi return null; } //System.out.println("*** No free work bucket -- waiting ***"); - dynamicSleep(Math.min(toWait, freeBucketWaitInterval), ctx); + dynamicSleep(Math.min(toWait, getFreeBucketWaitInterval()), ctx); ctx.reloadCoordinatorTask(result); ctx.reloadWorkerTask(result); if (reclaimWronglyAllocatedBuckets(ctx.coordinatorTask, result)) { @@ -229,8 +229,10 @@ private WorkBucketType getWorkBucketMultiNode(Context ctx, long freeBucketWaitTi throw new AssertionError(response); } } catch (PreconditionViolationException e) { - long delay = (long) (Math.random() * DELAY_INTERVAL); - LOGGER.debug("getWorkBucketMultiNode: conflict; this was attempt #{}; waiting {} ms", attempt, delay, e); + long delay = (long) (Math.random() * getDelayInterval()); + // temporary + LOGGER.info("getWorkBucketMultiNode: conflict; this was attempt #{}; waiting {} ms in {}, worker {}", + attempt, delay, ctx.coordinatorTask, ctx.workerTask, e); dynamicSleep(delay, ctx); ctx.reloadCoordinatorTask(result); ctx.reloadWorkerTask(result); @@ -243,6 +245,27 @@ private WorkBucketType getWorkBucketMultiNode(Context ctx, long freeBucketWaitTi } } + private long getFreeBucketWaitInterval() { + return freeBucketWaitIntervalOverride != null ? freeBucketWaitIntervalOverride : + getConfiguration().getWorkAllocationDefaultFreeBucketWaitInterval(); + } + + private int getMaxAttempts() { + return getConfiguration().getWorkAllocationMaxAttempts(); + } + + private long getDelayInterval() { + return getConfiguration().getWorkAllocationRetryInterval(); + } + + private long getInitialDelay() { + return getConfiguration().getWorkAllocationInitialDelay(); + } + + private TaskManagerConfiguration getConfiguration() { + return ((TaskManagerQuartzImpl) taskManager).getConfiguration(); + } + private void setOrUpdateEstimatedNumberOfBuckets(Task task, WorkSegmentationStrategy workStateStrategy, OperationResult result) throws SchemaException, ObjectAlreadyExistsException, ObjectNotFoundException { Integer number = workStateStrategy.estimateNumberOfBuckets(task.getWorkState()); @@ -255,8 +278,12 @@ private void setOrUpdateEstimatedNumberOfBuckets(Task task, WorkSegmentationStra } private void dynamicSleep(long delay, Context ctx) throws InterruptedException { + dynamicSleep(delay, ctx.canRunSupplier); + } + + private void dynamicSleep(long delay, Supplier canRunSupplier) throws InterruptedException { while (delay > 0) { - if (!ctx.canRun()) { + if (!canRun(canRunSupplier)) { throw new InterruptedException(); } Thread.sleep(Math.min(delay, DYNAMIC_SLEEP_INTERVAL)); @@ -556,8 +583,8 @@ private TaskWorkStateType getWorkState(Task task) throws SchemaException { } } - public void setFreeBucketWaitInterval(long freeBucketWaitInterval) { - this.freeBucketWaitInterval = freeBucketWaitInterval; + public void setFreeBucketWaitIntervalOverride(Long value) { + this.freeBucketWaitIntervalOverride = value; } // TODO @@ -593,4 +620,15 @@ public ObjectQuery narrowQueryForWorkBucket(Task workerTask, ObjectQuery query, // TODO update sorting criteria return updatedQuery; } + + public void executeInitialDelay(TaskQuartzImpl task) throws InterruptedException { + if (task.getWorkManagement() != null && task.getWorkManagement().getTaskKind() == TaskKindType.WORKER) { + long delay = (long) (Math.random() * getInitialDelay()); + if (delay != 0) { + // temporary info level logging + LOGGER.info("executeInitialDelay: waiting {} ms in {}", delay, task); + dynamicSleep(delay, task::canRun); + } + } + } } diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/work/segmentation/StringWorkSegmentationStrategy.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/work/segmentation/StringWorkSegmentationStrategy.java index f7adb502098..901e0c422a2 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/work/segmentation/StringWorkSegmentationStrategy.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/work/segmentation/StringWorkSegmentationStrategy.java @@ -209,7 +209,7 @@ private List processBoundaries() { return rv; } - private class Scanner { + private static class Scanner { final String string; int index; diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/work/segmentation/WorkSegmentationStrategyFactory.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/work/segmentation/WorkSegmentationStrategyFactory.java index 369a36d7a35..dfc37ed044a 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/work/segmentation/WorkSegmentationStrategyFactory.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/work/segmentation/WorkSegmentationStrategyFactory.java @@ -69,7 +69,7 @@ public WorkSegmentationStrategy createStrategy(TaskWorkManagementType configurat PrismContext.class); return constructor.newInstance(configuration, prismContext); } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) { - throw new SystemException("Couldn't instantiate work bucket segmentation strategy " + strategyClass + " for " + configuration); + throw new SystemException("Couldn't instantiate work bucket segmentation strategy " + strategyClass + " for " + configuration, e); } } diff --git a/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestPartitioning.java b/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestPartitioning.java index 860cd67a77a..e4aa7b24a5f 100644 --- a/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestPartitioning.java +++ b/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestPartitioning.java @@ -95,7 +95,7 @@ protected String coordinatorTaskOid(String TEST_NAME) { @PostConstruct public void initialize() throws Exception { super.initialize(); - workStateManager.setFreeBucketWaitInterval(1000L); + workStateManager.setFreeBucketWaitIntervalOverride(1000L); DebugUtil.setPrettyPrintBeansAs(PrismContext.LANG_YAML); } diff --git a/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestWorkBucketStrategies.java b/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestWorkBucketStrategies.java index b4d5a8378b0..5447ade1f66 100644 --- a/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestWorkBucketStrategies.java +++ b/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestWorkBucketStrategies.java @@ -106,7 +106,7 @@ protected String coordinatorTaskOid(String TEST_NAME) { @PostConstruct public void initialize() throws Exception { super.initialize(); - workStateManager.setFreeBucketWaitInterval(1000L); + workStateManager.setFreeBucketWaitIntervalOverride(1000L); DebugUtil.setPrettyPrintBeansAs(PrismContext.LANG_YAML); } diff --git a/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestWorkDistribution.java b/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestWorkDistribution.java index 0ffc8693b0c..0a446bf88b4 100644 --- a/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestWorkDistribution.java +++ b/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestWorkDistribution.java @@ -114,7 +114,7 @@ protected String coordinatorTaskOid(String TEST_NAME) { @PostConstruct public void initialize() throws Exception { super.initialize(); - workStateManager.setFreeBucketWaitInterval(1000L); + workStateManager.setFreeBucketWaitIntervalOverride(1000L); DebugUtil.setPrettyPrintBeansAs(PrismContext.LANG_YAML); } diff --git a/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestWorkersManagement.java b/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestWorkersManagement.java index 1b4eacedf62..7abad172208 100644 --- a/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestWorkersManagement.java +++ b/repo/task-quartz-impl/src/test/java/com/evolveum/midpoint/task/quartzimpl/TestWorkersManagement.java @@ -102,7 +102,7 @@ protected String coordinatorTaskOid(String TEST_NAME) { @PostConstruct public void initialize() throws Exception { super.initialize(); - workStateManager.setFreeBucketWaitInterval(1000L); + workStateManager.setFreeBucketWaitIntervalOverride(1000L); DebugUtil.setPrettyPrintBeansAs(PrismContext.LANG_YAML); } diff --git a/samples/model-client-sample/pom.xml b/samples/model-client-sample/pom.xml index c205db68a44..6317be9f7ae 100644 --- a/samples/model-client-sample/pom.xml +++ b/samples/model-client-sample/pom.xml @@ -62,6 +62,15 @@ + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + + org.apache.maven.plugins diff --git a/samples/policy/meta/policies-meta-approval.xml b/samples/policy/meta/policies-meta-approval.xml index f6f3b4a66b0..9a445a31ab5 100644 --- a/samples/policy/meta/policies-meta-approval.xml +++ b/samples/policy/meta/policies-meta-approval.xml @@ -87,7 +87,7 @@ Role approver - owner + approver firstDecides reject diff --git a/samples/tasks/bulk-actions/script-users-distinct.xml b/samples/tasks/bulk-actions/script-users-distinct.xml new file mode 100644 index 00000000000..6aa2c299958 --- /dev/null +++ b/samples/tasks/bulk-actions/script-users-distinct.xml @@ -0,0 +1,87 @@ + + + + script users (distinct) + runnable + + + + c:UserType + + + + assignment + + + + targetRef + + + + targetRef + + + + targetRef + + + + targetRef + + + + targetRef + + + + + + + + + + + true + + + + + execute-script + + script + + + log.info('Hello {}', input) + + + + + + + + + BulkActions + http://midpoint.evolveum.com/xml/ns/public/model/scripting/handler-3 + single + \ No newline at end of file diff --git a/samples/tasks/task-user-recompute-distinct.xml b/samples/tasks/task-user-recompute-distinct.xml new file mode 100644 index 00000000000..20c8cc2f730 --- /dev/null +++ b/samples/tasks/task-user-recompute-distinct.xml @@ -0,0 +1,71 @@ + + + + + + User Recompute (distinct) + + + + + assignment + + + + targetRef + + + + targetRef + + + + targetRef + + + + targetRef + + + + targetRef + + + + + + + + UserType + + + + + + runnable + http://midpoint.evolveum.com/xml/ns/public/model/synchronization/task/recompute/handler-3 + single + diff --git a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestReconNullValue.java b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestReconNullValue.java new file mode 100644 index 00000000000..b6abbb964de --- /dev/null +++ b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestReconNullValue.java @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2016-2017 Evolveum + * + * Licensed 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 com.evolveum.midpoint.testing.story; + +import static org.testng.Assert.assertEquals; +import static org.testng.AssertJUnit.assertNotNull; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.opends.server.types.DirectoryException; +import org.opends.server.types.Entry; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.testng.AssertJUnit; +import org.testng.annotations.AfterClass; +import org.testng.annotations.Test; + +import com.evolveum.midpoint.util.exception.PolicyViolationException; +import com.evolveum.midpoint.prism.PrismContainer; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.delta.ItemDelta; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.prism.util.PrismTestUtil; +import com.evolveum.midpoint.schema.constants.MidPointConstants; +import com.evolveum.midpoint.schema.processor.ResourceAttribute; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.MiscSchemaUtil; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.test.util.MidPointTestConstants; +import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.util.exception.CommunicationException; +import com.evolveum.midpoint.util.exception.ConfigurationException; +import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; +import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.exception.SecurityViolationException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.CredentialsType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PasswordType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; + +/** + * + * Recon should delete resourceAttribute + * + * Users and the roles being assigned in tests: + * User0: IT-Role-HR + + * + * + * + * @author michael gruber + * + */ +@ContextConfiguration(locations = { "classpath:ctx-story-test-main.xml" }) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +public class TestReconNullValue extends AbstractStoryTest { + + + public static final File TEST_DIR = new File(MidPointTestConstants.TEST_RESOURCES_DIR, "recon-null-value"); + + private static final String RESOURCE_OPENDJ_OID = "10000000-0000-0000-0000-000000000003"; + private static final String RESOURCE_OPENDJ_NAMESPACE = MidPointConstants.NS_RI; + /// private static final QName OPENDJ_ASSOCIATION_GROUP_NAME = new + /// QName(RESOURCE_OPENDJ_NAMESPACE, "group"); + + public static final String ORG_TOP_OID = "00000000-8888-6666-0000-100000000001"; + public static final String OBJECT_TEMPLATE_USER_OID = "10000000-0000-0000-0000-000000000222"; + + private static final String USER_0_NAME = "User0"; + + private static final String LDAP_INTENT_DEFAULT = "default"; + + private static final String ACCOUNT_ATTRIBUTE_TITLE = "title"; + + + private ResourceType resourceOpenDjType; + private PrismObject resourceOpenDj; + + @Override + protected String getTopOrgOid() { + return ORG_TOP_OID; + } + + private File getTestDir() { + return TEST_DIR; + } + + + @Override + protected void startResources() throws Exception { + openDJController.startCleanServerRI(); + } + + @AfterClass + public static void stopResources() throws Exception { + openDJController.stop(); + } + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + + //Resources + resourceOpenDj = importAndGetObjectFromFile(ResourceType.class, new File(getTestDir(), "resource-opendj.xml"), RESOURCE_OPENDJ_OID, initTask, initResult); + resourceOpenDjType = resourceOpenDj.asObjectable(); + openDJController.setResource(resourceOpenDj); + + //org + importObjectFromFile(new File(getTestDir(), "org-top.xml"), initResult); + + //role + importObjectFromFile(new File(getTestDir(), "role-ldap.xml"), initResult); + + //template + importObjectFromFile(new File(getTestDir(), "object-template-user.xml"), initResult); + setDefaultUserTemplate(OBJECT_TEMPLATE_USER_OID); + } + + @Test + public void test000Sanity() throws Exception { + final String TEST_NAME = "test000Sanity"; + TestUtil.displayTestTitle(this, TEST_NAME); + Task task = taskManager.createTaskInstance(TestTrafo.class.getName() + "." + TEST_NAME); + + OperationResult testResultOpenDj = modelService.testResource(RESOURCE_OPENDJ_OID, task); + TestUtil.assertSuccess(testResultOpenDj); + + dumpOrgTree(); + dumpLdap(); + display("FINISHED: test000Sanity"); + } + + + + @Test + public void test100CreateUsers() throws Exception { + final String TEST_NAME = "test200CreateUsers"; + TestUtil.displayTestTitle(this, TEST_NAME); + Task task = taskManager.createTaskInstance(TestReconNullValue.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + + PrismObject user0Before = createUser(USER_0_NAME, "givenName0", "familyName0", true); + + + // WHEN + TestUtil.displayWhen(TEST_NAME); + display("Adding user0", user0Before); + addObject(user0Before, task, result); + + // THEN + TestUtil.displayThen(TEST_NAME); + result.computeStatus(); + TestUtil.assertSuccess(result); + + PrismObject user0After = getObjectByName(UserType.class, USER_0_NAME); + display("user0 after", user0After); + + dumpOrgTree(); + + } + + /** + * add honorificPrefix + * + * in resource account value for title should have been added + * + */ + @Test + public void test140AddHonorificPrefix() throws Exception { + final String TEST_NAME = "test140AddHonorificPrefix"; + displayTestTitle(TEST_NAME); + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + dummyAuditService.clear(); + + + //TODO: best way to set extension properties? + PrismObject userBefore = getObjectByName(UserType.class, USER_0_NAME); + display("User before", userBefore); + PrismObject userNewPrism = userBefore.clone(); + prismContext.adopt(userNewPrism); + UserType userNew = userNewPrism.asObjectable(); + userNew.setHonorificPrefix(null); + + ObjectDelta delta = userBefore.diff(userNewPrism); + display("Modifying user with delta", delta); + + Collection> deltas = MiscSchemaUtil.createCollection(delta); + + // WHEN + displayWhen(TEST_NAME); + modelService.executeChanges(deltas, null, task, result); + + + // THEN + displayThen(TEST_NAME); + assertSuccess(result); + + PrismObject userAfter = getObjectByName(UserType.class, USER_0_NAME); + display("User after deleting attribute honorificPrefix", userAfter); + + + String accountOid = getLinkRefOid(userAfter, RESOURCE_OPENDJ_OID); + + // Check shadow + PrismObject accountShadow = repositoryService.getObject(ShadowType.class, accountOid, null, result); + display("accountShadow after attribute deletion", accountShadow); + + // Check account + PrismObject accountModel = modelService.getObject(ShadowType.class, accountOid, null, task, result); + display("accountModel after attribute deletion", accountModel); + + PrismAsserts.assertNoItem(accountModel, openDJController.getAttributePath(ACCOUNT_ATTRIBUTE_TITLE)); + + } + + + /** + * remove title in Resoure Attributer + * + * in resource account value for title should have been removed + * + */ + @Test //MID-4567 + public void test150RemoveTitleRA() throws Exception { + final String TEST_NAME = "test150RemoveTitleRA"; + displayTestTitle(TEST_NAME); + + // GIVEN + Task task = createTask(TEST_NAME); + OperationResult result = task.getResult(); + dummyAuditService.clear(); + + + //TODO: best way to set extension properties? + PrismObject userBefore = getObjectByName(UserType.class, USER_0_NAME); + display("User before", userBefore); + + + openDJController.executeLdifChange("dn: uid="+USER_0_NAME+",ou=people,dc=example,dc=com\n"+ + "changetype: modify\n"+ + "add: title\n"+ + "title: Earl"); + + // WHEN + displayWhen(TEST_NAME); + modelService.recompute(UserType.class, userBefore.getOid(), null, task, result); + + + + // THEN + displayThen(TEST_NAME); + assertSuccess(result); + + PrismObject userAfter = getObjectByName(UserType.class, USER_0_NAME); + display("User smack after adding attribute title", userAfter); + + + String accountOid = getLinkRefOid(userAfter, RESOURCE_OPENDJ_OID); + + // Check shadow + PrismObject accountShadow = repositoryService.getObject(ShadowType.class, accountOid, null, result); + display("accountShadow after attribute addition", accountShadow); + + // Check account + PrismObject accountModel = modelService.getObject(ShadowType.class, accountOid, null, task, result); + display("accountModel after attribute addition", accountModel); + + PrismAsserts.assertNoItem(accountModel, openDJController.getAttributePath( ACCOUNT_ATTRIBUTE_TITLE)); + + } + + private void dumpLdap() throws DirectoryException { + display("LDAP server tree", openDJController.dumpTree()); + display("LDAP server content", openDJController.dumpEntries()); + } + + + protected PrismObject getObjectByName( + Class clazz, String name) throws SchemaException, ObjectNotFoundException, SecurityViolationException, + CommunicationException, ConfigurationException, ExpressionEvaluationException { + PrismObject object = (PrismObject) findObjectByName(clazz, name); + assertNotNull("The object " + name + " of type " + clazz + " is missing!", object); + display(clazz + " " + name, object); + PrismAsserts.assertPropertyValue(object, F.F_NAME, PrismTestUtil.createPolyString(name)); + return object; + } + +} \ No newline at end of file diff --git a/testing/story/src/test/resources/recon-null-value/object-template-user.xml b/testing/story/src/test/resources/recon-null-value/object-template-user.xml new file mode 100644 index 00000000000..28b9d6578ad --- /dev/null +++ b/testing/story/src/test/resources/recon-null-value/object-template-user.xml @@ -0,0 +1,47 @@ + + + + User Template + + + + + + RoleType + + + name + + + + + + + + + assignment + + + + diff --git a/testing/story/src/test/resources/recon-null-value/org-top.xml b/testing/story/src/test/resources/recon-null-value/org-top.xml new file mode 100644 index 00000000000..18acdeaa51e --- /dev/null +++ b/testing/story/src/test/resources/recon-null-value/org-top.xml @@ -0,0 +1,25 @@ + + + + + TOP + Top + 0000 + functional + diff --git a/testing/story/src/test/resources/recon-null-value/resource-opendj.xml b/testing/story/src/test/resources/recon-null-value/resource-opendj.xml new file mode 100644 index 00000000000..89ac7cdc6fa --- /dev/null +++ b/testing/story/src/test/resources/recon-null-value/resource-opendj.xml @@ -0,0 +1,191 @@ + + + + + + Embedded Test OpenDJ + + + Dummy description, just for the test + + + c:connectorType + com.evolveum.polygon.connector.ldap.LdapConnector + + + + + + + + 10389 + localhost + dc=example,dc=com + cn=directory manager + + secret + + auto + entryUUID + ds-pwp-account-disabled + isMemberOf + uniqueMember + + + + false + + false + + false + + + + + + + + ri:groupOfUniqueNames + ri:organizationalUnit + ri:groupOfURLs + ri:ds-virtual-static-group + ri:inetOrgPerson + ri:organizationalPerson + ri:person + ri:top + + + + + + + account + default + Default Account + true + ri:inetOrgPerson + + ri:dn + Distinguished Name + + Name cannot be weak. Changes in name trigger object rename. + + $user/name + + + + + + + + + ri:cn + Common Name + + + fullName + + + + + + ri:sn + + + familyName + + + + + + ri:givenName + + + givenName + + + + + + ri:title + false + + strong + + honorificPrefix + + + + + + ri:isMemberOf + + + + + + http://prism.evolveum.com/xml/ns/public/matching-rule-3#stringIgnoreCase + attributes/ri:dn + cn=Directory Manager + + + + + + + + + + + + + + + + + + + + + + + + + + ri:ds-pwp-account-disabled + + true + + + + + + diff --git a/testing/story/src/test/resources/recon-null-value/role-ldap.xml b/testing/story/src/test/resources/recon-null-value/role-ldap.xml new file mode 100644 index 00000000000..cab58a597ac --- /dev/null +++ b/testing/story/src/test/resources/recon-null-value/role-ldap.xml @@ -0,0 +1,35 @@ + + role-ldap + + + + + + + name + Embedded Test OpenDJ + + + + account + default + + + + + + + + \ No newline at end of file diff --git a/testing/story/testng-integration.xml b/testing/story/testng-integration.xml index adfe9cdf9fd..3749fba3fdc 100644 --- a/testing/story/testng-integration.xml +++ b/testing/story/testng-integration.xml @@ -49,6 +49,7 @@ + diff --git a/tools/ninja/pom.xml b/tools/ninja/pom.xml index 21e7eb5d981..33b24e8a8c6 100644 --- a/tools/ninja/pom.xml +++ b/tools/ninja/pom.xml @@ -250,6 +250,9 @@ repackage + + ZIP + diff --git a/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/util/NinjaUtils.java b/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/util/NinjaUtils.java index 36d046adda1..800bf5d9071 100644 --- a/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/util/NinjaUtils.java +++ b/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/util/NinjaUtils.java @@ -70,7 +70,7 @@ public static JCommander setupCommandLineParser() { } JCommander jc = builder.build(); - jc.setProgramName("java [-cp ] -jar ninja.jar"); + jc.setProgramName("java [-Dloader.path=] -jar ninja.jar"); jc.setColumnSize(150); jc.setAtFileCharset(Charset.forName(base.getCharset())); diff --git a/tools/xjc-plugin/src/main/java/com/evolveum/midpoint/schema/xjc/schema/SchemaProcessor.java b/tools/xjc-plugin/src/main/java/com/evolveum/midpoint/schema/xjc/schema/SchemaProcessor.java index 199ad63bf0e..cfe2b1c1e50 100644 --- a/tools/xjc-plugin/src/main/java/com/evolveum/midpoint/schema/xjc/schema/SchemaProcessor.java +++ b/tools/xjc-plugin/src/main/java/com/evolveum/midpoint/schema/xjc/schema/SchemaProcessor.java @@ -1117,8 +1117,8 @@ private void updateFields(Outline outline) { print("Updating fields and get/set methods: " + classOutline.implClass.fullName()); - for (String field : fields.keySet()) { - JFieldVar fieldVar = fields.get(field); + for (Map.Entry field : fields.entrySet()) { + JFieldVar fieldVar = field.getValue(); // marks a:rawType fields with @Raw - this has to be executed for any bean, not only for prism containers if (hasAnnotation(classOutline, fieldVar, A_RAW_TYPE) != null) { annotateFieldAsRaw(fieldVar); @@ -1134,7 +1134,7 @@ private void updateFields(Outline outline) { } allFieldsToBeRemoved.forEach((jDefinedClass, jFieldVars) -> { - jFieldVars.forEach(field -> jDefinedClass.removeField(field)); + jFieldVars.forEach(jDefinedClass::removeField); }); } @@ -1148,6 +1148,7 @@ private void processContainerFields(ClassOutline classOutline, Map fieldsToBeRemoved = new ArrayList<>(); + // WARNING: cannot change to entrySet. For some reason entrySet does not work here. for (String field : fields.keySet()) { JFieldVar fieldVar = fields.get(field); if (isAuxiliaryField(fieldVar)) { @@ -1183,8 +1184,8 @@ private void processContainerFields(ClassOutline classOutline, Map fields = sourceClass.implClass.fields(); - for (String field : fields.keySet()) { - JFieldVar fieldVar = fields.get(field); + for (Map.Entry field : fields.entrySet()) { + JFieldVar fieldVar = field.getValue(); if (!isAuxiliaryField(fieldVar) && !hasAnnotationClass(fieldVar, XmlAnyElement.class)) { createFluentFieldMethods(fieldVar, targetClass, sourceClass); }