diff --git a/gui/admin-gui/pom.xml b/gui/admin-gui/pom.xml index 78e86326e54..364faef3c7a 100644 --- a/gui/admin-gui/pom.xml +++ b/gui/admin-gui/pom.xml @@ -321,6 +321,7 @@ system-init 4.2-SNAPSHOT + com.evolveum.midpoint.repo @@ -334,6 +335,12 @@ ${project.version} runtime + + com.evolveum.midpoint.model + rest-impl + ${project.version} + + org.codehaus.groovy groovy-all diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/AssignmentPopup.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/AssignmentPopup.java index 8670f75c317..b3d31d34d12 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/AssignmentPopup.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/AssignmentPopup.java @@ -25,7 +25,7 @@ import com.evolveum.midpoint.gui.api.component.tabs.CountablePanelTab; import com.evolveum.midpoint.gui.api.component.tabs.PanelTab; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.schema.constants.ObjectTypes; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/ContainerableListPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/ContainerableListPanel.java index cba7c8f6c44..396ae7be6a0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/ContainerableListPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/ContainerableListPanel.java @@ -7,7 +7,7 @@ package com.evolveum.midpoint.gui.api.component; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ObjectPaging; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/FocusTypeAssignmentPopupTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/FocusTypeAssignmentPopupTabPanel.java index 017759c53e9..f7ef1a2c3e8 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/FocusTypeAssignmentPopupTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/FocusTypeAssignmentPopupTabPanel.java @@ -16,8 +16,8 @@ import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.panel.Fragment; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.query.ObjectFilter; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/MainObjectListPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/MainObjectListPanel.java index f8da09f36ae..f664ed0d8f4 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/MainObjectListPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/MainObjectListPanel.java @@ -76,8 +76,8 @@ protected IColumn, String> createCheckboxColumn() { } @Override - protected IColumn, String> createNameColumn(IModel columnNameModel, String itemPath) { - if (StringUtils.isEmpty(itemPath)) { + protected IColumn, String> createNameColumn(IModel columnNameModel, String itemPath, ExpressionType expression) { + if (StringUtils.isEmpty(itemPath) && expression == null) { return new ObjectNameColumn(columnNameModel == null ? createStringResource("ObjectType.name") : columnNameModel) { private static final long serialVersionUID = 1L; @@ -94,7 +94,7 @@ public boolean isClickable(IModel> rowModel) { }; } else { return new ObjectNameColumn(columnNameModel == null ? createStringResource("ObjectType.name") : columnNameModel, - itemPath) { + itemPath, expression, getPageBase()) { private static final long serialVersionUID = 1L; @Override diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/ObjectBrowserPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/ObjectBrowserPanel.html index 85a71fcb45a..432f8b49497 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/ObjectBrowserPanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/ObjectBrowserPanel.html @@ -7,6 +7,7 @@ +
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/ObjectBrowserPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/ObjectBrowserPanel.java index e8c2da80dd6..a9e1bca336d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/ObjectBrowserPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/ObjectBrowserPanel.java @@ -12,12 +12,15 @@ import javax.xml.namespace.QName; +import com.evolveum.midpoint.gui.api.component.result.MessagePanel; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.constants.ObjectTypes; +import com.evolveum.midpoint.web.component.util.VisibleBehaviour; + import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.OnChangeAjaxBehavior; @@ -41,6 +44,7 @@ public class ObjectBrowserPanel extends BasePanel imple private static final String ID_TYPE = "type"; private static final String ID_TYPE_PANEL = "typePanel"; private static final String ID_TABLE = "table"; + private static final String ID_WARNING_MESSAGE = "warningMessage"; private static final String ID_BUTTON_ADD = "addButton"; @@ -100,6 +104,11 @@ protected void onInitialize(){ } private void initLayout() { + MessagePanel warningMessage = new MessagePanel(ID_WARNING_MESSAGE, MessagePanel.MessagePanelType.WARN, getWarningMessageModel()); + warningMessage.setOutputMarkupId(true); + warningMessage.add(new VisibleBehaviour(() -> getWarningMessageModel() != null)); + add(warningMessage); + List supported = new ArrayList<>(); for (QName qname : supportedTypes) { supported.add(ObjectTypes.getObjectTypeFromTypeQName(qname)); @@ -218,6 +227,10 @@ private Collection> getOptions() { return null; } + protected IModel getWarningMessageModel(){ + return null; + } + @Override public int getWidth() { return 900; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/ObjectListPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/ObjectListPanel.java index 51683c19258..fb27d6018c3 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/ObjectListPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/ObjectListPanel.java @@ -14,14 +14,20 @@ import com.evolveum.midpoint.model.api.authentication.CompiledObjectCollectionView; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.common.expression.ExpressionUtil; +import com.evolveum.midpoint.repo.common.expression.ExpressionVariables; +import com.evolveum.midpoint.schema.constants.ExpressionConstants; import com.evolveum.midpoint.schema.constants.ObjectTypes; 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.util.exception.*; import com.evolveum.midpoint.web.component.data.column.InlineMenuButtonColumn; import com.evolveum.midpoint.web.component.search.*; import com.evolveum.midpoint.web.component.util.SelectableBean; import com.evolveum.midpoint.web.component.util.SerializableSupplier; import com.evolveum.midpoint.web.component.util.VisibleBehaviour; +import com.evolveum.midpoint.web.page.admin.server.dto.OperationResultStatusPresentationProperties; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.apache.commons.lang3.StringUtils; import org.apache.wicket.Component; @@ -336,27 +342,31 @@ protected List, String>> getCustomColumnsTransformed(L } IColumn, String> column; for (GuiObjectColumnType customColumn : customColumns) { - if (customColumn.getPath() == null) { + if (customColumn.getPath() == null && customColumn.getExpression() == null) { continue; } - ItemPath columnPath = customColumn.getPath().getItemPath(); + ItemPath columnPath = customColumn.getPath() == null ? null : customColumn.getPath().getItemPath(); // TODO this throws an exception for some kinds of invalid paths like e.g. fullName/norm (but we probably should fix prisms in that case!) - ItemDefinition itemDefinition = getPageBase().getPrismContext().getSchemaRegistry() - .findObjectDefinitionByCompileTimeClass(type.getClassDefinition()) - .findItemDefinition(columnPath); - if (itemDefinition == null) { - LOGGER.warn("Unknown path '{}' in a definition of column '{}'", columnPath, customColumn.getName()); - continue; + ExpressionType expression = customColumn.getExpression(); + if (columnPath != null) { + ItemDefinition itemDefinition = getPageBase().getPrismContext().getSchemaRegistry() + .findObjectDefinitionByCompileTimeClass(type.getClassDefinition()) + .findItemDefinition(columnPath); + if (itemDefinition == null && expression == null) { + LOGGER.warn("Unknown path '{}' in a definition of column '{}'", columnPath, customColumn.getName()); + continue; + } } if (WebComponentUtil.getElementVisibility(customColumn.getVisibility())) { IModel columnDisplayModel = customColumn.getDisplay() != null && customColumn.getDisplay().getLabel() != null ? Model.of(customColumn.getDisplay().getLabel().getOrig()) : - createStringResource(getItemDisplayName(customColumn)); + (customColumn.getPath() != null ? createStringResource(getItemDisplayName(customColumn)) : + Model.of(customColumn.getName())); if (customColumns.indexOf(customColumn) == 0) { // TODO what if a complex path is provided here? - column = createNameColumn(columnDisplayModel, customColumn.getPath().toString()); + column = createNameColumn(columnDisplayModel, customColumn.getPath() == null ? "" : customColumn.getPath().toString(), expression); } else { column = new AbstractExportableColumn, String>(columnDisplayModel, null) { private static final long serialVersionUID = 1L; @@ -373,7 +383,31 @@ public IModel getDataModel(IModel> rowModel) { if (value == null) { return Model.of(""); } - Item item = value.asPrismContainerValue().findItem(columnPath); + Item item = null; + if (columnPath != null) { + item = value.asPrismContainerValue().findItem(columnPath); + } + Item object = value.asPrismObject(); + if (item != null) { + object = item; + } + if (expression != null) { + Task task = getPageBase().createSimpleTask("evaluate column expression"); + try { + ExpressionVariables expressionVariables = new ExpressionVariables(); + expressionVariables.put(ExpressionConstants.VAR_OBJECT, object, object.getClass()); + String stringValue = ExpressionUtil.evaluateStringExpression(expressionVariables, getPageBase().getPrismContext(), expression, + MiscSchemaUtil.getExpressionProfile(), getPageBase().getExpressionFactory(), "evaluate column expression", + task, task.getResult()).iterator().next(); + return Model.of(stringValue); + } catch (SchemaException | ExpressionEvaluationException | ObjectNotFoundException | CommunicationException + | ConfigurationException | SecurityViolationException e) { + LOGGER.error("Couldn't execute expression for name column"); + OperationResult result = task.getResult(); + OperationResultStatusPresentationProperties props = OperationResultStatusPresentationProperties.parseOperationalResultStatus(result.getStatus()); + return getPageBase().createStringResource(props.getStatusLabelKey()); + } + } if (item != null) { if (item.getDefinition() != null && item.getDefinition().getValueEnumerationRef() != null && item.getDefinition().getValueEnumerationRef().getOid() != null){ @@ -439,7 +473,7 @@ protected List, String>> initColumns() { IColumn, String> iconColumn = (IColumn) ColumnUtils.createIconColumn(getPageBase()); columns.add(iconColumn); - IColumn, String> nameColumn = createNameColumn(null, null); + IColumn, String> nameColumn = createNameColumn(null, null, null); columns.add(nameColumn); List, String>> others = createColumns(); @@ -854,7 +888,8 @@ protected IColumn, String> createIconColumn(){ return (IColumn) ColumnUtils.createIconColumn(getPageBase()); } - protected abstract IColumn, String> createNameColumn(IModel columnNameModel, String itemPath); + protected abstract IColumn, String> createNameColumn(IModel columnNameModel, String itemPath, + ExpressionType expression); protected abstract List, String>> createColumns(); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/PopupObjectListPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/PopupObjectListPanel.java index 321c2e97290..84d12f69d88 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/PopupObjectListPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/PopupObjectListPanel.java @@ -12,11 +12,22 @@ import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.repo.common.expression.ExpressionUtil; +import com.evolveum.midpoint.repo.common.expression.ExpressionVariables; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.schema.constants.ExpressionConstants; +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.util.exception.*; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.component.data.column.PolyStringPropertyColumn; import com.evolveum.midpoint.web.component.util.SelectableBeanImpl; import com.evolveum.midpoint.web.component.util.SerializableSupplier; +import com.evolveum.midpoint.web.page.admin.server.dto.OperationResultStatusPresentationProperties; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; import org.apache.commons.lang3.StringUtils; import org.apache.wicket.ajax.AjaxRequestTarget; @@ -39,6 +50,8 @@ public abstract class PopupObjectListPanel extends ObjectListPanel { private static final long serialVersionUID = 1L; + private static final Trace LOGGER = TraceManager.getTrace(PopupObjectListPanel.class); + /** * @param defaultType specifies type of the object that will be selected by default */ @@ -80,13 +93,17 @@ protected IModel getEnabled(IModel> rowModel) { } @Override - protected IColumn, String> createNameColumn(IModel columnNameModel, String itemPath) { + protected IColumn, String> createNameColumn(IModel columnNameModel, String itemPath, ExpressionType expression) { if (!isMultiselect()) { + String propertyExpression = SelectableBeanImpl.F_VALUE + "." + (StringUtils.isEmpty(itemPath) ? "name" : itemPath); + String sortProperty = StringUtils.isEmpty(itemPath) ? ObjectType.F_NAME.getLocalPart() : itemPath; + if (expression != null) { + propertyExpression = SelectableBeanImpl.F_VALUE +(StringUtils.isEmpty(itemPath) ? "" : ("." + itemPath)); + sortProperty = StringUtils.isEmpty(itemPath) ? "" : itemPath; + } return new LinkColumn>( columnNameModel == null ? createStringResource("ObjectType.name") : columnNameModel, - StringUtils.isEmpty(itemPath) ? ObjectType.F_NAME.getLocalPart() : itemPath, - SelectableBeanImpl.F_VALUE + "." + - (StringUtils.isEmpty(itemPath) ? "name" : itemPath)) { + sortProperty, propertyExpression) { private static final long serialVersionUID = 1L; @Override @@ -102,23 +119,67 @@ protected IModel createLinkModel(IModel> rowModel) { public void onClick(AjaxRequestTarget target, IModel> rowModel) { O object = rowModel.getObject().getValue(); onSelectPerformed(target, object); + } + @Override + public IModel getDataModel(IModel> rowModel) { + if (expression != null) { + Object object = new PropertyModel<>(rowModel, getPropertyExpression()).getObject(); + return evaluateColumnExpression(object, expression); + } else { + return super.getDataModel(rowModel); + } } }; } else { - if (StringUtils.isEmpty(itemPath) || ObjectType.F_NAME.getLocalPart().equals(itemPath)){ + if ((StringUtils.isEmpty(itemPath) || ObjectType.F_NAME.getLocalPart().equals(itemPath)) && expression == null){ return new PolyStringPropertyColumn>(columnNameModel == null ? createStringResource("userBrowserDialog.name") : columnNameModel, ObjectType.F_NAME.getLocalPart(), "value.name"); } else { + String propertyExpression = SelectableBeanImpl.F_VALUE + "." + itemPath; + String sortProperty = itemPath; + if (expression != null) { + propertyExpression = SelectableBeanImpl.F_VALUE +(StringUtils.isEmpty(itemPath) ? "" : ("." + itemPath)); + sortProperty = StringUtils.isEmpty(itemPath) ? "" : itemPath; + } return new PropertyColumn( columnNameModel == null ? createStringResource("userBrowserDialog.name") : columnNameModel, - itemPath,SelectableBeanImpl.F_VALUE + "." + itemPath); + sortProperty, propertyExpression){ + + @Override + public IModel getDataModel(IModel rowModel) { + if (expression != null) { + Object object = new PropertyModel<>(rowModel, getPropertyExpression()).getObject(); + return evaluateColumnExpression(object, expression); + } else { + return super.getDataModel(rowModel); + } + } + }; } } } + private IModel evaluateColumnExpression(Object object, ExpressionType expression) { + Task task = getPageBase().createSimpleTask("evaluate column expression"); + try { + ExpressionVariables expressionVariables = new ExpressionVariables(); + expressionVariables.put(ExpressionConstants.VAR_OBJECT, object, object.getClass()); + String stringValue = ExpressionUtil.evaluateStringExpression(expressionVariables, getPageBase().getPrismContext(), expression, + MiscSchemaUtil.getExpressionProfile(), getPageBase().getExpressionFactory(), "evaluate column expression", + task, task.getResult()).iterator().next(); + return Model.of(stringValue); + } catch (SchemaException | ExpressionEvaluationException | ObjectNotFoundException | CommunicationException + | ConfigurationException | SecurityViolationException e) { + LOGGER.error("Couldn't execute expression for name column"); + OperationResult result = task.getResult(); + OperationResultStatusPresentationProperties props = OperationResultStatusPresentationProperties.parseOperationalResultStatus(result.getStatus()); + return getPageBase().createStringResource(props.getStatusLabelKey()); + } + } + @Override protected List, String>> createColumns() { return ColumnUtils.getDefaultColumns(getType()); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/button/CsvDownloadButtonPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/button/CsvDownloadButtonPanel.java index 076d451fcc4..fb46bb5ad33 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/button/CsvDownloadButtonPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/button/CsvDownloadButtonPanel.java @@ -8,6 +8,7 @@ import java.io.IOException; import java.io.OutputStream; +import java.util.ArrayList; import java.util.List; import com.evolveum.midpoint.util.logging.Trace; @@ -15,8 +16,11 @@ import com.evolveum.midpoint.web.component.data.BaseSortableDataProvider; import com.evolveum.midpoint.web.component.dialog.ConfirmationPanel; import com.evolveum.midpoint.web.component.data.SelectableBeanObjectDataProvider; +import com.evolveum.midpoint.web.component.dialog.SelectExportingColumnsPanel; + import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable; +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; import org.apache.wicket.extensions.markup.html.repeater.data.table.export.CSVDataExporter; import org.apache.wicket.extensions.markup.html.repeater.data.table.export.ExportToolbar; import org.apache.wicket.extensions.markup.html.repeater.data.table.export.IExportableColumn; @@ -39,6 +43,9 @@ public abstract class CsvDownloadButtonPanel extends BasePanel { private static final String ID_EXPORT_DATA = "exportData"; private final boolean canCountBeforeExporting; + List exportableColumnsIndex = new ArrayList<>(); + + private IModel> exportedColumnsIndex = Model.ofList(new ArrayList<>()); public CsvDownloadButtonPanel(String id, boolean canCountBeforeExporting) { super(id); @@ -64,7 +71,7 @@ public void exportData(IDataProvider dataProvider, List List> getExportableColumns() { + List> exportableColumns = new ArrayList<>(); + List> allColumns = getDataTable().getColumns(); + for (Integer index : exportableColumnsIndex) { + exportableColumns.add((IExportableColumn) allColumns.get(index)); + } + return exportableColumns; + } + protected abstract DataTable getDataTable(); protected abstract String getFilename(); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/password/PasswordPropertyPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/password/PasswordPropertyPanel.java index 26337a9e861..05dd5ce839d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/password/PasswordPropertyPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/component/password/PasswordPropertyPanel.java @@ -6,11 +6,12 @@ */ package com.evolveum.midpoint.gui.api.component.password; -import com.evolveum.midpoint.gui.api.factory.GuiComponentFactory; -import com.evolveum.midpoint.gui.impl.factory.ItemRealValueModel; -import com.evolveum.midpoint.gui.impl.prism.*; +import com.evolveum.midpoint.gui.impl.factory.panel.ItemRealValueModel; +import com.evolveum.midpoint.gui.impl.prism.panel.ItemPanelSettings; +import com.evolveum.midpoint.gui.impl.prism.panel.PrismPropertyPanel; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismPropertyValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; import com.evolveum.midpoint.web.component.prism.ValueStatus; -import com.evolveum.midpoint.web.page.admin.users.PageUser; import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; import org.apache.wicket.Component; import org.apache.wicket.markup.html.list.ListItem; @@ -19,7 +20,7 @@ /** * Created by honchar */ -public class PasswordPropertyPanel extends PrismPropertyPanel{ +public class PasswordPropertyPanel extends PrismPropertyPanel { private static final long serialVersionUID = 1L; private static final String ID_PASSWORD_PANEL= "passwordPanel"; @@ -29,8 +30,7 @@ public PasswordPropertyPanel(String id, IModel> item, GuiComponentFactory factory, - ItemVisibilityHandler visibilityHandler, ItemEditabilityHandler editabilityHandler) { + protected Component createValuePanel(ListItem> item) { PasswordPanel passwordPanel = new PasswordPanel(ID_PASSWORD_PANEL, new ItemRealValueModel<>(item.getModel()), getModelObject() != null && getModelObject().isReadOnly(), @@ -54,9 +54,4 @@ protected void changePasswordPerformed(){ } - @Override - protected void createButtons(ListItem> item) { - //nothing to do - } - } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/AbstractGuiComponentFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/AbstractGuiComponentFactory.java index 109f71a667b..e897a95cd98 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/AbstractGuiComponentFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/AbstractGuiComponentFactory.java @@ -7,21 +7,16 @@ package com.evolveum.midpoint.gui.api.factory; -import java.util.ArrayList; import java.util.List; import com.evolveum.midpoint.common.LocalizationService; import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.prism.polystring.PolyString; -import com.evolveum.prism.xml.ns._public.types_3.PolyStringTranslationType; -import org.apache.commons.lang3.StringUtils; + import org.apache.wicket.feedback.ComponentFeedbackMessageFilter; import org.apache.wicket.markup.html.panel.Panel; -import com.evolveum.midpoint.gui.impl.factory.PrismPropertyPanelContext; -import com.evolveum.midpoint.web.component.prism.InputPanel; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableRowType; +import com.evolveum.midpoint.gui.impl.factory.panel.PrismPropertyPanelContext; import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; import org.springframework.beans.factory.annotation.Autowired; @@ -39,7 +34,7 @@ public GuiComponentRegistry getRegistry() { @Override public Panel createPanel(PrismPropertyPanelContext panelCtx) { Panel panel = getPanel(panelCtx); - +// panelCtx.getFeedback().setFilter(new ComponentFeedbackMessageFilter(panel)); return panel; } @@ -50,7 +45,5 @@ public Integer getOrder() { protected abstract Panel getPanel(PrismPropertyPanelContext panelCtx); - protected List prepareAutoCompleteList(String input, LookupTableType lookupTable, LocalizationService localizationService) { - return WebComponentUtil.prepareAutoCompleteList(lookupTable, input, localizationService); - } + } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/GuiComponentFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/GuiComponentFactory.java index 7c015e0fde4..397d8249597 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/GuiComponentFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/GuiComponentFactory.java @@ -7,10 +7,12 @@ package com.evolveum.midpoint.gui.api.factory; +import org.apache.wicket.Component; +import org.apache.wicket.feedback.ComponentFeedbackMessageFilter; import org.apache.wicket.markup.html.panel.Panel; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.impl.factory.ItemPanelContext; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.impl.factory.panel.ItemPanelContext; public interface GuiComponentFactory{ // public void register(); @@ -21,6 +23,10 @@ public interface GuiComponentFactory{ Integer getOrder(); + default void configure(T panelCtx, Component component) { +// panelCtx.getFeedback().setFilter(new ComponentFeedbackMessageFilter(component)); + } + // Panel build(PanelContext panelContext); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ItemWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/wrapper/ItemWrapperFactory.java similarity index 69% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ItemWrapperFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/wrapper/ItemWrapperFactory.java index 92001789ffa..ff639586b3e 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ItemWrapperFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/wrapper/ItemWrapperFactory.java @@ -4,12 +4,12 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.api.factory.wrapper; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; import com.evolveum.midpoint.prism.Item; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismValue; @@ -24,7 +24,7 @@ public interface ItemWrapperFactory parent, ItemDefinition def, WrapperContext context) throws SchemaException; - IW createWrapper(Item childContainer, ItemStatus status, WrapperContext context) throws SchemaException; + IW createWrapper(PrismContainerValueWrapper parent, Item childContainer, ItemStatus status, WrapperContext context) throws SchemaException; VW createValueWrapper(IW parent, PV value, ValueStatus status, WrapperContext context) throws SchemaException; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/wrapper/PrismContainerWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/wrapper/PrismContainerWrapperFactory.java new file mode 100644 index 00000000000..18ea16ba52d --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/wrapper/PrismContainerWrapperFactory.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.api.factory.wrapper; + +import com.evolveum.midpoint.gui.api.prism.ItemStatus; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.Item; +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.web.component.prism.ValueStatus; + +/** + * @author katka + * + */ +public interface PrismContainerWrapperFactory extends ItemWrapperFactory, PrismContainerValueWrapper, PrismContainerValue> { + + + PrismContainerValueWrapper createContainerValueWrapper(PrismContainerWrapper objectWrapper, PrismContainerValue objectValue, ValueStatus status, WrapperContext context); + +// ItemWrapper createChildWrapper(ItemDefinition def, PrismContainerValueWrapper containerValueWrapper, WrapperContext context) throws SchemaException; +// ItemWrapper createChildWrapper(PrismContainerValueWrapper parent, I childItem, ItemStatus status, WrapperContext context) throws SchemaException; + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismObjectWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/wrapper/PrismObjectWrapperFactory.java similarity index 82% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismObjectWrapperFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/wrapper/PrismObjectWrapperFactory.java index 1ddc6546578..71125a553ad 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismObjectWrapperFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/wrapper/PrismObjectWrapperFactory.java @@ -4,12 +4,11 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.api.factory.wrapper; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectValue; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/WrapperContext.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/wrapper/WrapperContext.java similarity index 97% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/WrapperContext.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/wrapper/WrapperContext.java index 5ce5e23c750..5742a98f69e 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/WrapperContext.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/wrapper/WrapperContext.java @@ -4,7 +4,7 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.api.factory.wrapper; import com.evolveum.midpoint.gui.api.prism.ItemStatus; import com.evolveum.midpoint.prism.PrismObject; @@ -16,7 +16,8 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.VirtualContainerItemSpecificationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.VirtualContainersSpecificationType; -import javax.xml.namespace.QName; +import org.jetbrains.annotations.NotNull; + import java.util.Collection; import java.util.List; @@ -113,7 +114,6 @@ public void setShowEmpty(boolean showEmpty) { this.showEmpty = showEmpty; } - public ItemStatus getObjectStatus() { return objectStatus; } @@ -146,6 +146,7 @@ public List getVirtualItemSpecification() return virtualItemSpecification; } + @NotNull public PrismObject getObject() { return object; } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/WrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/wrapper/WrapperFactory.java similarity index 89% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/WrapperFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/wrapper/WrapperFactory.java index 280f53e24b7..64163d591dc 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/WrapperFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/factory/wrapper/WrapperFactory.java @@ -4,7 +4,7 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.api.factory.wrapper; import com.evolveum.midpoint.prism.ItemDefinition; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/page/PageBase.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/page/PageBase.java index 5073cf5730b..378781c8ab0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/page/PageBase.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/page/PageBase.java @@ -15,6 +15,8 @@ import javax.management.ObjectName; import javax.xml.namespace.QName; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismContainerWrapperFactory; +import com.evolveum.midpoint.gui.impl.prism.panel.ItemPanelSettings; import com.evolveum.midpoint.web.page.admin.PageAdminObjectDetails; import com.evolveum.midpoint.web.page.admin.certification.*; @@ -71,19 +73,18 @@ import com.evolveum.midpoint.gui.api.component.result.OpResult; import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; import com.evolveum.midpoint.gui.api.util.ModelServiceLocator; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; import com.evolveum.midpoint.gui.impl.error.ErrorPanel; -import com.evolveum.midpoint.gui.impl.factory.ItemWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; -import com.evolveum.midpoint.gui.impl.prism.ItemPanelSettings; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValuePanel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; +import com.evolveum.midpoint.gui.api.factory.wrapper.ItemWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.impl.prism.panel.PrismContainerValuePanel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; import com.evolveum.midpoint.model.api.*; import com.evolveum.midpoint.model.api.authentication.CompiledGuiProfile; import com.evolveum.midpoint.model.api.authentication.CompiledObjectCollectionView; @@ -2678,7 +2679,6 @@ public void reloadShoppingCartIcon(AjaxRequestTarget target) { public AsyncWebProcessManager getAsyncWebProcessManager() { return MidPointApplication.get().getAsyncWebProcessManager(); } - @Override public Locale getLocale() { return getSession().getLocale(); @@ -2697,7 +2697,7 @@ public PrismObjectWrapperFactory findObjectWrapperFact public VW createValueWrapper(IW parentWrapper, PV newValue, ValueStatus status, WrapperContext context) throws SchemaException { - ItemWrapperFactory factory = (ItemWrapperFactory) registry.findWrapperFactory(parentWrapper); + ItemWrapperFactory factory = registry.findWrapperFactory(parentWrapper); return factory.createValueWrapper(parentWrapper, newValue, status, context); @@ -2705,19 +2705,19 @@ public IW createItemWrapper(ID def, PrismContainerValueWrapper parent, WrapperContext ctx) throws SchemaException { - ItemWrapperFactory factory = (ItemWrapperFactory) registry.findWrapperFactory(def); + PrismContainerWrapperFactory factory = registry.findContainerWrapperFactory(parent.getDefinition()); ctx.setShowEmpty(true); ctx.setCreateIfEmpty(true); - return factory.createWrapper(parent, def, ctx); + return (IW) factory.createWrapper(parent, def, ctx); } public IW createItemWrapper(I item, ItemStatus status, WrapperContext ctx) throws SchemaException { - ItemWrapperFactory factory = (ItemWrapperFactory) registry.findWrapperFactory(item.getDefinition()); + ItemWrapperFactory factory = registry.findWrapperFactory(item.getDefinition()); ctx.setCreateIfEmpty(true); - return factory.createWrapper(item, status, ctx); + return factory.createWrapper(null, item, status, ctx); } @@ -2744,7 +2744,7 @@ public Panel initItemPanel(String panelId, QName typeNa } } - public , C extends Containerable> Panel initContainerValuePanel(String id, IModel model, + public Panel initContainerValuePanel(String id, IModel> model, ItemPanelSettings settings) { //TODO find from registry first return new PrismContainerValuePanel<>(id, model, settings); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemEditabilityHandler.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ItemEditabilityHandler.java similarity index 63% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemEditabilityHandler.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ItemEditabilityHandler.java index 69f2ff9aa00..bc8ef404d75 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemEditabilityHandler.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ItemEditabilityHandler.java @@ -4,14 +4,10 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.api.prism.wrapper; import java.io.Serializable; -import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.web.component.prism.ItemVisibility; - /** * @author honchar * diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemMandatoryHandler.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ItemMandatoryHandler.java similarity index 64% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemMandatoryHandler.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ItemMandatoryHandler.java index 997130ffda7..3bfb47c8427 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemMandatoryHandler.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ItemMandatoryHandler.java @@ -4,15 +4,13 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; - -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +package com.evolveum.midpoint.gui.api.prism.wrapper; import java.io.Serializable; @FunctionalInterface public interface ItemMandatoryHandler extends Serializable { - boolean isMandatory(ItemWrapper itemWrapper); + boolean isMandatory(ItemWrapper itemWrapper); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemVisibilityHandler.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ItemVisibilityHandler.java similarity index 81% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemVisibilityHandler.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ItemVisibilityHandler.java index d9ca35257ab..cd9d46aae01 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemVisibilityHandler.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ItemVisibilityHandler.java @@ -4,11 +4,10 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.api.prism.wrapper; import java.io.Serializable; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; import com.evolveum.midpoint.web.component.prism.ItemVisibility; /** diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/ItemWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ItemWrapper.java similarity index 66% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/ItemWrapper.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ItemWrapper.java index f453815ab48..21076df70f1 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/ItemWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ItemWrapper.java @@ -1,83 +1,88 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.api.prism; - -import java.io.Serializable; -import java.util.Collection; -import java.util.List; - -import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.impl.prism.ItemVisibilityHandler; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; -import com.evolveum.midpoint.prism.Item; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.PrismValue; -import com.evolveum.midpoint.prism.Revivable; -import com.evolveum.midpoint.prism.delta.ItemDelta; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.util.DebugDumpable; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserInterfaceElementVisibilityType; - -/** - * @author katka - * - */ -public interface ItemWrapper, ID extends ItemDefinition, VW extends PrismValueWrapper> extends ItemDefinition, Revivable, DebugDumpable, Serializable { - - - String debugDump(int indent); - - void setVisibleOverwrite(UserInterfaceElementVisibilityType visible); - boolean isVisible(PrismContainerValueWrapper parentContainer, ItemVisibilityHandler visibilityHandler); - - boolean checkRequired(PageBase pageBase); - - PrismContainerValueWrapper getParent(); - - boolean isShowEmpty(); - - void setShowEmpty(boolean isShowEmpty, boolean recursive); - - boolean isShowInVirtualContainer(); - - void setShowInVirtualContainer(boolean showInVirtualContainer); - - ItemPath getPath(); - - //NEW - - boolean isReadOnly(); - - void setReadOnly(boolean readOnly); - - ExpressionType getFormComponentValidator(); - - List getValues(); - VW getValue() throws SchemaException; - - boolean isStripe(); - void setStripe(boolean stripe); - - I getItem(); - - boolean isColumn(); - void setColumn(boolean column); - - > void applyDelta(D delta) throws SchemaException; - - > Collection getDelta() throws SchemaException; - - ItemStatus findObjectStatus(); - - , O extends ObjectType> OW findObjectWrapper(); - - ItemStatus getStatus(); -} +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.api.prism.wrapper; + +import java.io.Serializable; +import java.util.Collection; +import java.util.List; + +import com.evolveum.midpoint.gui.api.page.PageBase; +import com.evolveum.midpoint.gui.api.prism.ItemStatus; +import com.evolveum.midpoint.gui.api.util.ModelServiceLocator; +import com.evolveum.midpoint.prism.Item; +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.prism.Revivable; +import com.evolveum.midpoint.prism.delta.ItemDelta; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.util.DebugDumpable; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserInterfaceElementVisibilityType; + +/** + * @author katka + * + */ +public interface ItemWrapper extends ItemDefinition, Revivable, DebugDumpable, Serializable { + + + String debugDump(int indent); + + void setVisibleOverwrite(UserInterfaceElementVisibilityType visible); + UserInterfaceElementVisibilityType getVisibleOverwrite(); + boolean isVisible(PrismContainerValueWrapper parentContainer, ItemVisibilityHandler visibilityHandler); + + boolean checkRequired(PageBase pageBase); + + PrismContainerValueWrapper getParent(); + + boolean isShowEmpty(); + + void setShowEmpty(boolean isShowEmpty, boolean recursive); + + boolean isShowInVirtualContainer(); + + void setShowInVirtualContainer(boolean showInVirtualContainer); + + ItemPath getPath(); + + //NEW + + boolean isReadOnly(); + + void setReadOnly(boolean readOnly); + + ExpressionType getFormComponentValidator(); + + List getValues(); + VW getValue() throws SchemaException; + + boolean isStripe(); + void setStripe(boolean stripe); + + I getItem(); + + boolean isColumn(); + void setColumn(boolean column); + + > Collection getDelta() throws SchemaException; + + ItemStatus findObjectStatus(); + + , O extends ObjectType> OW findObjectWrapper(); + + ItemStatus getStatus(); + + boolean isEmpty(); + + void remove(VW valueWrapper, ModelServiceLocator locator) throws SchemaException; + void removeAll(ModelServiceLocator locator) throws SchemaException; + + void add(PV newValueWrapper, ModelServiceLocator locator) throws SchemaException; +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerValueWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismContainerValueWrapper.java similarity index 89% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerValueWrapper.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismContainerValueWrapper.java index 2b82e1b8514..715a79e2bc5 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerValueWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismContainerValueWrapper.java @@ -4,12 +4,10 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.api.prism.wrapper; import java.util.List; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; @@ -48,9 +46,9 @@ public interface PrismContainerValueWrapper extends Pri List> getContainers(); - List> getNonContainers(); + List> getNonContainers(); - List> getItems(); + List> getItems(); PrismContainerWrapper findContainer(ItemPath path) throws SchemaException; PrismPropertyWrapper findProperty(ItemPath propertyPath) throws SchemaException; @@ -83,4 +81,6 @@ public interface PrismContainerValueWrapper extends Pri void setVirtualContainerItems(List virtualItems); boolean isVirtual(); + PrismContainerDefinition getDefinition(); + } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/PrismContainerWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismContainerWrapper.java similarity index 73% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/PrismContainerWrapper.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismContainerWrapper.java index b672da35942..a4f282d41ba 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/PrismContainerWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismContainerWrapper.java @@ -4,11 +4,9 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.api.prism; +package com.evolveum.midpoint.gui.api.prism.wrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismReferenceWrapper; +import com.evolveum.midpoint.gui.api.prism.ItemStatus; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.util.exception.SchemaException; @@ -17,7 +15,7 @@ * @author katka * */ -public interface PrismContainerWrapper extends ItemWrapper, PrismContainer, PrismContainerDefinition, PrismContainerValueWrapper>, PrismContainerDefinition{ +public interface PrismContainerWrapper extends ItemWrapper, PrismContainerValueWrapper>, PrismContainerDefinition{ void setExpanded(boolean expanded); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismObjectValueWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismObjectValueWrapper.java similarity index 88% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismObjectValueWrapper.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismObjectValueWrapper.java index 16b27fb8b46..5a8de9c45f2 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismObjectValueWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismObjectValueWrapper.java @@ -4,7 +4,7 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.api.prism.wrapper; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/PrismObjectWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismObjectWrapper.java similarity index 87% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/PrismObjectWrapper.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismObjectWrapper.java index baf8b3ac34e..306b7b8a39f 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/PrismObjectWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismObjectWrapper.java @@ -4,9 +4,8 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.api.prism; +package com.evolveum.midpoint.gui.api.prism.wrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismObjectValueWrapper; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.util.exception.SchemaException; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismPropertyWrapper.java similarity index 67% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyWrapper.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismPropertyWrapper.java index 8c52afcc1f8..f537591b72b 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismPropertyWrapper.java @@ -4,19 +4,18 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.api.prism.wrapper; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismPropertyValueWrapper; import com.evolveum.midpoint.prism.PrismProperty; import com.evolveum.midpoint.prism.PrismPropertyDefinition; -import com.evolveum.midpoint.prism.PrismPropertyValue; import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; /** * @author katka * */ -public interface PrismPropertyWrapper extends ItemWrapper, PrismProperty, PrismPropertyDefinition, PrismPropertyValueWrapper>, PrismPropertyDefinition { +public interface PrismPropertyWrapper extends ItemWrapper, PrismPropertyValueWrapper>, PrismPropertyDefinition { LookupTableType getPredefinedValues(); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismReferenceWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismReferenceWrapper.java similarity index 68% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismReferenceWrapper.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismReferenceWrapper.java index 76dd0e78b56..3e0bbe1f6ea 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismReferenceWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismReferenceWrapper.java @@ -4,16 +4,14 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.api.prism.wrapper; import java.util.List; - import javax.xml.namespace.QName; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismReferenceValueWrapperImpl; import com.evolveum.midpoint.prism.PrismReference; import com.evolveum.midpoint.prism.PrismReferenceDefinition; -import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.prism.Referencable; import com.evolveum.midpoint.prism.query.ObjectFilter; @@ -21,7 +19,7 @@ * @author katka * */ -public interface PrismReferenceWrapper extends ItemWrapper>, PrismReferenceDefinition { +public interface PrismReferenceWrapper extends ItemWrapper>, PrismReferenceDefinition { ObjectFilter getFilter(); void setFilter(ObjectFilter filter); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismValueWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismValueWrapper.java similarity index 75% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismValueWrapper.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismValueWrapper.java index 0251c0b4490..23a69128fe7 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismValueWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/PrismValueWrapper.java @@ -4,11 +4,10 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.api.prism.wrapper; import java.io.Serializable; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.prism.delta.ItemDelta; @@ -32,7 +31,8 @@ public interface PrismValueWrapper extends Serializable V getOldValue(); IW getParent(); - , ID extends ItemDefinition> void addToDelta(D delta) throws SchemaException; + > void addToDelta(D delta) throws SchemaException; + + boolean isVisible(); -// void applyDelta(ID delta) throws SchemaException; } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ResourceAttributeWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ResourceAttributeWrapper.java similarity index 88% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ResourceAttributeWrapper.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ResourceAttributeWrapper.java index 6c7b4bb7f03..de621952de5 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ResourceAttributeWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ResourceAttributeWrapper.java @@ -4,7 +4,7 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.api.prism.wrapper; import com.evolveum.midpoint.common.refinery.RefinedAttributeDefinition; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/ShadowWrapper.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ShadowWrapper.java similarity index 92% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/ShadowWrapper.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ShadowWrapper.java index 1a56f7c371c..a0de21c0d0d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/ShadowWrapper.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/prism/wrapper/ShadowWrapper.java @@ -4,7 +4,7 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.api.prism; +package com.evolveum.midpoint.gui.api.prism.wrapper; import com.evolveum.midpoint.web.page.admin.users.dto.UserDtoStatus; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/registry/GuiComponentRegistry.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/registry/GuiComponentRegistry.java index 859e08bfa3a..36f103d1666 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/registry/GuiComponentRegistry.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/registry/GuiComponentRegistry.java @@ -12,13 +12,12 @@ import javax.xml.namespace.QName; import com.evolveum.midpoint.gui.api.factory.GuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.impl.factory.ItemWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.PrismObjectDefinition; -import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismContainerWrapperFactory; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.factory.wrapper.ItemWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; +import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; public interface GuiComponentRegistry extends Serializable { @@ -33,6 +32,8 @@ public interface GuiComponentRegistry extends Serializable { ItemWrapperFactory findWrapperFactory(ItemDefinition def); + PrismContainerWrapperFactory findContainerWrapperFactory(PrismContainerDefinition def); + PrismObjectWrapperFactory getObjectWrapperFactory(PrismObjectDefinition objectDef); void addToRegistry(ItemWrapperFactory factory); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/ModelServiceLocator.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/ModelServiceLocator.java index d58be9062d6..564345fd313 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/ModelServiceLocator.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/ModelServiceLocator.java @@ -8,11 +8,11 @@ import com.evolveum.midpoint.common.LocalizationService; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; import com.evolveum.midpoint.model.api.ModelInteractionService; import com.evolveum.midpoint.model.api.ModelService; import com.evolveum.midpoint.model.api.authentication.CompiledGuiProfile; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebComponentUtil.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebComponentUtil.java index 6261fcc826b..cc3eb9f4693 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebComponentUtil.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebComponentUtil.java @@ -16,18 +16,16 @@ import com.evolveum.midpoint.gui.api.model.NonEmptyModel; import com.evolveum.midpoint.gui.api.model.ReadOnlyValueModel; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; import com.evolveum.midpoint.gui.impl.component.icon.CompositedIcon; import com.evolveum.midpoint.gui.impl.component.icon.CompositedIconBuilder; import com.evolveum.midpoint.gui.impl.component.icon.IconCssStyle; import com.evolveum.midpoint.gui.impl.component.icon.LayeredIconCssStyle; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismPropertyValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; import com.evolveum.midpoint.model.api.*; import com.evolveum.midpoint.model.api.authentication.CompiledObjectCollectionView; import com.evolveum.midpoint.model.api.authentication.CompiledGuiProfile; @@ -57,11 +55,8 @@ import com.evolveum.midpoint.schema.util.*; import com.evolveum.midpoint.security.api.AuthorizationConstants; import com.evolveum.midpoint.security.api.MidPointPrincipal; -import com.evolveum.midpoint.security.enforcer.api.AuthorizationParameters; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.task.api.TaskBinding; import com.evolveum.midpoint.task.api.TaskCategory; -import com.evolveum.midpoint.task.api.TaskExecutionStatus; import com.evolveum.midpoint.util.*; import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.LoggingUtils; @@ -90,7 +85,6 @@ import com.evolveum.midpoint.web.component.util.Selectable; import com.evolveum.midpoint.web.component.util.SelectableBeanImpl; import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; -import com.evolveum.midpoint.web.model.PrismPropertyWrapperModel; import com.evolveum.midpoint.web.page.PageDialog; import com.evolveum.midpoint.web.page.admin.archetype.PageArchetype; import com.evolveum.midpoint.web.page.admin.cases.PageCase; @@ -159,7 +153,6 @@ import org.apache.wicket.markup.repeater.data.IDataProvider; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; -import org.apache.wicket.model.PropertyModel; import org.apache.wicket.model.StringResourceModel; import org.apache.wicket.request.IRequestHandler; import org.apache.wicket.request.cycle.RequestCycle; @@ -2642,7 +2635,7 @@ public static PolyStringType getCollectionLabel(DisplayType viewDisplayType, Col return null; } - public static ItemVisibility checkShadowActivationAndPasswordVisibility(ItemWrapper itemWrapper, + public static ItemVisibility checkShadowActivationAndPasswordVisibility(ItemWrapper itemWrapper, ShadowType shadowType) { ObjectReferenceType resourceRef = shadowType.getResourceRef(); if (resourceRef == null) { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebPrismUtil.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebPrismUtil.java index a576d5aeadd..9fd718c5015 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebPrismUtil.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebPrismUtil.java @@ -1,147 +1,160 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.api.util; - -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.impl.prism.ItemPanel; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismReferenceWrapper; -import com.evolveum.midpoint.prism.*; -import com.evolveum.midpoint.prism.path.ItemPath; - -import com.evolveum.midpoint.schema.GetOperationOptions; -import com.evolveum.midpoint.util.QNameUtil; -import com.evolveum.midpoint.util.logging.LoggingUtils; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; - -import org.apache.commons.lang.StringUtils; -import org.apache.wicket.ajax.AjaxRequestTarget; - -import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.prism.ValueStatus; - -import javax.xml.namespace.QName; -import java.util.Collections; -import java.util.List; - -/** - * @author katka - * - */ -public class WebPrismUtil { - - private static final Trace LOGGER = TraceManager.getTrace(WebPrismUtil.class); - - private static final String DOT_CLASS = WebPrismUtil.class.getName() + "."; - private static final String OPERATION_CREATE_NEW_VALUE = DOT_CLASS + "createNewValue"; - - public static , I extends Item, V extends PrismValue> String getHelpText(ID def) { - if (def == null) { - return null; - } - String doc = def.getHelp(); - if (StringUtils.isEmpty(doc)) { - doc = def.getDocumentation(); - if (StringUtils.isEmpty(doc)) { - return null; - } - } - - return doc.replaceAll("\\s{2,}", " ").trim(); - } - - - public static VW createNewValueWrapper(IW itemWrapper, PV newValue, PageBase pageBase, AjaxRequestTarget target) { - LOGGER.debug("Adding value to {}", itemWrapper); - - OperationResult result = new OperationResult(OPERATION_CREATE_NEW_VALUE); - - VW newValueWrapper = null; - try { - - if (!(itemWrapper instanceof PrismContainerWrapper)) { - itemWrapper.getItem().add(newValue); - } - - Task task = pageBase.createSimpleTask(OPERATION_CREATE_NEW_VALUE); - - WrapperContext context = new WrapperContext(task, result); - context.setObjectStatus(itemWrapper.findObjectStatus()); - context.setShowEmpty(true); - context.setCreateIfEmpty(true); - - newValueWrapper = pageBase.createValueWrapper(itemWrapper, newValue, ValueStatus.ADDED, context); - itemWrapper.getValues().add(newValueWrapper); - result.recordSuccess(); - - } catch (SchemaException e) { - LOGGER.error("Cannot create new value for {}", itemWrapper, e); - result.recordFatalError(pageBase.createStringResource("WebPrismUtil.message.createNewValueWrapper.fatalError", newValue, e.getMessage()).getString(), e); - target.add(pageBase.getFeedbackPanel()); - } - - return newValueWrapper; - } - - public static IW findItemWrapper(ItemWrapper child, ItemPath absoluthPathToFind, Class wrapperClass) { - PrismObjectWrapper taskWrapper = child.findObjectWrapper(); - try { - return taskWrapper.findItem(ItemPath.create(absoluthPathToFind), wrapperClass); - } catch (SchemaException e) { - LoggingUtils.logUnexpectedException(LOGGER, "Cannot get obejct reference value, {}", e, e.getMessage()); - return null; - } - } - - public static PrismReferenceWrapper findReferenceWrapper(ItemWrapper child, ItemPath pathToFind) { - return findItemWrapper(child, pathToFind, PrismReferenceWrapper.class); - } - - public static PrismPropertyWrapper findPropertyWrapper(ItemWrapper child, ItemPath pathToFind) { - return findItemWrapper(child, pathToFind, PrismPropertyWrapper.class); - } - - public static PrismReferenceValue findSingleReferenceValue(ItemWrapper child, ItemPath pathToFind) { - PrismReferenceWrapper objectRefWrapper = findReferenceWrapper(child, pathToFind); - if (objectRefWrapper == null) { - return null; - } - - try { - return objectRefWrapper.getValue().getNewValue(); - } catch (SchemaException e) { - LoggingUtils.logUnexpectedException(LOGGER, "Cannot get object reference value, {}", e, e.getMessage()); - return null; - } - } - - public static PrismPropertyValue findSinglePropertyValue(ItemWrapper child, ItemPath pathToFind) { - PrismPropertyWrapper propertyWrapper = findPropertyWrapper(child, pathToFind); - if (propertyWrapper == null) { - return null; - } - - try { - return propertyWrapper.getValue().getNewValue(); - } catch (SchemaException e) { - LoggingUtils.logUnexpectedException(LOGGER, "Cannot get object reference value, {}", e, e.getMessage()); - return null; - } - } -} +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.api.util; + +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismReferenceWrapper; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.path.ItemPath; + +import com.evolveum.midpoint.util.logging.LoggingUtils; + +import org.apache.commons.lang.StringUtils; +import org.apache.wicket.ajax.AjaxRequestTarget; + +import com.evolveum.midpoint.gui.api.page.PageBase; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.component.prism.ValueStatus; + +/** + * @author katka + * + */ +public class WebPrismUtil { + + private static final Trace LOGGER = TraceManager.getTrace(WebPrismUtil.class); + + private static final String DOT_CLASS = WebPrismUtil.class.getName() + "."; + private static final String OPERATION_CREATE_NEW_VALUE = DOT_CLASS + "createNewValue"; + + public static , I extends Item> String getHelpText(ID def) { + if (def == null) { + return null; + } + String doc = def.getHelp(); + if (StringUtils.isEmpty(doc)) { + doc = def.getDocumentation(); + if (StringUtils.isEmpty(doc)) { + return null; + } + } + + return doc.replaceAll("\\s{2,}", " ").trim(); + } + + + public static VW createNewValueWrapper(IW itemWrapper, PV newValue, PageBase pageBase, AjaxRequestTarget target) { + LOGGER.debug("Adding value to {}", itemWrapper); + + OperationResult result = new OperationResult(OPERATION_CREATE_NEW_VALUE); + + VW newValueWrapper = null; + try { + + if (!(itemWrapper instanceof PrismContainerWrapper)) { + itemWrapper.getItem().add(newValue); + } + + Task task = pageBase.createSimpleTask(OPERATION_CREATE_NEW_VALUE); + + WrapperContext context = new WrapperContext(task, result); + context.setObjectStatus(itemWrapper.findObjectStatus()); + context.setShowEmpty(true); + context.setCreateIfEmpty(true); + + newValueWrapper = pageBase.createValueWrapper(itemWrapper, newValue, ValueStatus.ADDED, context); + itemWrapper.getValues().add(newValueWrapper); + result.recordSuccess(); + + } catch (SchemaException e) { + LOGGER.error("Cannot create new value for {}", itemWrapper, e); + result.recordFatalError(pageBase.createStringResource("WebPrismUtil.message.createNewValueWrapper.fatalError", newValue, e.getMessage()).getString(), e); + target.add(pageBase.getFeedbackPanel()); + } + + return newValueWrapper; + } + + public static VW createNewValueWrapper(IW itemWrapper, PV newValue, ModelServiceLocator modelServiceLocator) throws SchemaException { + LOGGER.debug("Adding value to {}", itemWrapper); + + + + +// if (!(itemWrapper instanceof PrismContainerWrapper)) { +// itemWrapper.getItem().add(newValue); +// } + + Task task = modelServiceLocator.createSimpleTask(OPERATION_CREATE_NEW_VALUE); + OperationResult result = new OperationResult(OPERATION_CREATE_NEW_VALUE); + + WrapperContext context = new WrapperContext(task, result); + context.setObjectStatus(itemWrapper.findObjectStatus()); + context.setShowEmpty(true); + context.setCreateIfEmpty(true); + + VW newValueWrapper = modelServiceLocator.createValueWrapper(itemWrapper, newValue, ValueStatus.ADDED, context); + result.recordSuccess(); + + return newValueWrapper; + } + + public static IW findItemWrapper(ItemWrapper child, ItemPath absoluthPathToFind, Class wrapperClass) { + PrismObjectWrapper taskWrapper = child.findObjectWrapper(); + try { + return taskWrapper.findItem(ItemPath.create(absoluthPathToFind), wrapperClass); + } catch (SchemaException e) { + LoggingUtils.logUnexpectedException(LOGGER, "Cannot get obejct reference value, {}", e, e.getMessage()); + return null; + } + } + + public static PrismReferenceWrapper findReferenceWrapper(ItemWrapper child, ItemPath pathToFind) { + return findItemWrapper(child, pathToFind, PrismReferenceWrapper.class); + } + + public static PrismPropertyWrapper findPropertyWrapper(ItemWrapper child, ItemPath pathToFind) { + return findItemWrapper(child, pathToFind, PrismPropertyWrapper.class); + } + + public static PrismReferenceValue findSingleReferenceValue(ItemWrapper child, ItemPath pathToFind) { + PrismReferenceWrapper objectRefWrapper = findReferenceWrapper(child, pathToFind); + if (objectRefWrapper == null) { + return null; + } + + try { + return objectRefWrapper.getValue().getNewValue(); + } catch (SchemaException e) { + LoggingUtils.logUnexpectedException(LOGGER, "Cannot get object reference value, {}", e, e.getMessage()); + return null; + } + } + + public static PrismPropertyValue findSinglePropertyValue(ItemWrapper child, ItemPath pathToFind) { + PrismPropertyWrapper propertyWrapper = findPropertyWrapper(child, pathToFind); + if (propertyWrapper == null) { + return null; + } + + try { + return propertyWrapper.getValue().getNewValue(); + } catch (SchemaException e) { + LoggingUtils.logUnexpectedException(LOGGER, "Cannot get object reference value, {}", e, e.getMessage()); + return null; + } + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerDetailsPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerDetailsPanel.html index ab46bc94005..2e063fe32d3 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerDetailsPanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerDetailsPanel.html @@ -11,7 +11,9 @@
-
+
+
+
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerDetailsPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerDetailsPanel.java index 82c30b54710..2f5067455ad 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerDetailsPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerDetailsPanel.java @@ -6,9 +6,10 @@ */ package com.evolveum.midpoint.gui.impl.component; -import com.evolveum.midpoint.gui.impl.prism.ItemMandatoryHandler; -import com.evolveum.midpoint.gui.impl.prism.ItemPanelSettings; -import com.evolveum.midpoint.gui.impl.prism.ItemPanelSettingsBuilder; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemMandatoryHandler; + +import com.evolveum.midpoint.gui.impl.prism.panel.ItemPanelSettings; +import com.evolveum.midpoint.gui.impl.prism.panel.ItemPanelSettingsBuilder; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.panel.Panel; @@ -16,11 +17,9 @@ import com.evolveum.midpoint.gui.api.component.BasePanel; import com.evolveum.midpoint.gui.api.component.DisplayNamePanel; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.prism.Containerable; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.web.component.form.Form; import com.evolveum.midpoint.web.component.prism.ItemVisibility; /** @@ -69,7 +68,6 @@ protected void addBasicContainerValuePanel(String idPanel){ protected Panel getBasicContainerValuePanel(String idPanel){ ItemPanelSettingsBuilder builder = new ItemPanelSettingsBuilder() .visibilityHandler(wrapper -> getBasicTabVisibity(wrapper)) - .showOnTopLevel(true) .editabilityHandler(wrapper -> getBasicTabEditability(wrapper)); if (getMandatoryHandler() != null) { @@ -81,11 +79,11 @@ protected Panel getBasicContainerValuePanel(String idPanel){ return containerValue; } - protected ItemVisibility getBasicTabVisibity(ItemWrapper itemWrapper) { //, ItemPath parentPath) { + protected ItemVisibility getBasicTabVisibity(ItemWrapper itemWrapper) { //, ItemPath parentPath) { return ItemVisibility.AUTO; } - protected boolean getBasicTabEditability(ItemWrapper itemWrapper) { + protected boolean getBasicTabEditability(ItemWrapper itemWrapper) { return true; } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerDetailsWithSummaryPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerDetailsWithSummaryPanel.java index b04e22b679b..6e58a1fec18 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerDetailsWithSummaryPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerDetailsWithSummaryPanel.java @@ -9,7 +9,7 @@ import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.model.IModel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.prism.Containerable; /** diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerListPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerListPanel.java index e76b0ee58f6..bf7479c5949 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerListPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerListPanel.java @@ -30,11 +30,11 @@ import com.evolveum.midpoint.gui.api.GuiStyleConstants; import com.evolveum.midpoint.gui.api.component.BasePanel; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.api.util.WebPrismUtil; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.gui.impl.component.icon.CompositedIconBuilder; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; import com.evolveum.midpoint.gui.impl.util.GuiImplUtil; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContainerDefinition; @@ -44,7 +44,6 @@ import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.MultifunctionalButton; import com.evolveum.midpoint.web.component.data.BoxedTablePanel; import com.evolveum.midpoint.web.component.data.Table; import com.evolveum.midpoint.web.component.data.column.ColumnMenuAction; @@ -518,7 +517,6 @@ public List getDefaultMenuActions() { menuItems.add(new ButtonInlineMenuItem(createStringResource("pageAdminFocus.button.delete")) { private static final long serialVersionUID = 1L; - @Override public CompositedIconBuilder getIconCompositedBuilder(){ return getDefaultCompositedIconBuilder(GuiStyleConstants.CLASS_DELETE_MENU_ITEM); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerListPanelWithDetailsPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerListPanelWithDetailsPanel.java index 725bb7ceb0a..ab398a263b4 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerListPanelWithDetailsPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/MultivalueContainerListPanelWithDetailsPanel.java @@ -17,8 +17,8 @@ import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.model.IModel; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.util.logging.Trace; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/AbstractItemWrapperColumn.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/AbstractItemWrapperColumn.java index 9c44727fa4c..ee6f3fc4db4 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/AbstractItemWrapperColumn.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/AbstractItemWrapperColumn.java @@ -12,19 +12,12 @@ 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.export.IExportableColumn; -import org.apache.wicket.markup.html.basic.Label; -import org.apache.wicket.markup.html.list.ListItem; -import org.apache.wicket.markup.html.list.ListView; -import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.markup.repeater.Item; import org.apache.wicket.model.IModel; -import org.apache.wicket.model.PropertyModel; -import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.path.ItemPath; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/AbstractItemWrapperColumnPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/AbstractItemWrapperColumnPanel.java index e8a8819340d..b68507d300c 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/AbstractItemWrapperColumnPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/AbstractItemWrapperColumnPanel.java @@ -16,9 +16,9 @@ import com.evolveum.midpoint.gui.api.component.BasePanel; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.impl.component.data.column.AbstractItemWrapperColumn.ColumnType; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; import com.evolveum.midpoint.prism.path.ItemPath; /** diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/CompositedIconColumn.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/CompositedIconColumn.java index 66b3cdf555e..d3928612a63 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/CompositedIconColumn.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/CompositedIconColumn.java @@ -11,6 +11,7 @@ import org.apache.commons.lang3.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.extensions.markup.html.repeater.data.table.export.IExportableColumn; import org.apache.wicket.markup.repeater.Item; import org.apache.wicket.model.IModel; @@ -19,7 +20,7 @@ /** * @author skublik */ -public abstract class CompositedIconColumn extends AbstractColumn implements IExportableColumn { +public abstract class CompositedIconColumn extends AbstractColumn implements IColumn { private static final long serialVersionUID = 1L; public CompositedIconColumn(IModel displayModel) { @@ -43,7 +44,6 @@ public void populateItem(Item> cellItem, String componentId, I protected abstract CompositedIcon getCompositedIcon(final IModel rowModel); - @Override public IModel getDataModel(IModel rowModel) { return Model.of(""); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/LinkPrismPropertyColumn.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/LinkPrismPropertyColumn.java index b540f99b7bf..dd40af1cce8 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/LinkPrismPropertyColumn.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/LinkPrismPropertyColumn.java @@ -7,22 +7,7 @@ package com.evolveum.midpoint.gui.impl.component.data.column; -import org.apache.wicket.Component; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.extensions.markup.html.repeater.data.table.export.IExportableColumn; -import org.apache.wicket.markup.html.list.ListItem; -import org.apache.wicket.model.IModel; - -import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.impl.factory.ItemRealValueModel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; import com.evolveum.midpoint.prism.Containerable; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.web.component.data.column.LinkPanel; /** * @author skublik diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismContainerWrapperColumn.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismContainerWrapperColumn.java index 2b27f863788..9d4ccf78125 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismContainerWrapperColumn.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismContainerWrapperColumn.java @@ -10,10 +10,10 @@ import org.apache.wicket.model.IModel; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerColumnHeaderPanel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.impl.prism.panel.PrismContainerColumnHeaderPanel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.path.ItemPath; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismContainerWrapperColumnPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismContainerWrapperColumnPanel.java index c143c9e1535..ec4143f2d76 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismContainerWrapperColumnPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismContainerWrapperColumnPanel.java @@ -6,7 +6,6 @@ */ package com.evolveum.midpoint.gui.impl.component.data.column; -import java.util.ArrayList; import java.util.List; import org.apache.commons.collections4.CollectionUtils; @@ -14,14 +13,13 @@ import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.IModel; -import com.ctc.wstx.util.StringUtil; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; import com.evolveum.midpoint.gui.impl.component.data.column.AbstractItemWrapperColumn.ColumnType; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismPropertyValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.schema.util.PolicyRuleTypeUtil; import com.evolveum.midpoint.util.exception.SchemaException; @@ -33,14 +31,10 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; import com.evolveum.midpoint.xml.ns._public.common.common_3.LifecycleStateModelType; import com.evolveum.midpoint.xml.ns._public.common.common_3.LifecycleStateType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultStatusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.PendingOperationExecutionStatusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.PendingOperationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.PendingOperationTypeType; import com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyActionsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyConstraintsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectAssociationType; -import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; /** * @author katka diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismPropertyWrapperColumn.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismPropertyWrapperColumn.java index 0b62dcaea4c..72d822fd1f5 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismPropertyWrapperColumn.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismPropertyWrapperColumn.java @@ -13,11 +13,11 @@ import org.apache.wicket.model.Model; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyHeaderPanel; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.impl.prism.panel.PrismPropertyHeaderPanel; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismPropertyValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.path.ItemPath; @@ -49,7 +49,18 @@ public IModel getDataModel(IModel> rowModel) { @Override protected Component createHeader(String componentId, IModel> mainModel) { - return new PrismPropertyHeaderPanel<>(componentId, new PrismPropertyWrapperHeaderModel(mainModel, itemName, pageBase)); + return new PrismPropertyHeaderPanel(componentId, new PrismPropertyWrapperHeaderModel(mainModel, itemName, pageBase)) { + + @Override + protected boolean isAddButtonVisible() { + return false; + } + + @Override + protected boolean isButtonEnabled() { + return false; + } + }; } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismPropertyWrapperColumnPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismPropertyWrapperColumnPanel.java index d082958d109..bc3e08e1df5 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismPropertyWrapperColumnPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismPropertyWrapperColumnPanel.java @@ -12,10 +12,10 @@ import com.evolveum.midpoint.gui.impl.component.data.column.AbstractItemWrapperColumn.ColumnType; import com.evolveum.midpoint.gui.impl.error.ErrorPanel; -import com.evolveum.midpoint.gui.impl.factory.ItemRealValueModel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; +import com.evolveum.midpoint.gui.impl.factory.panel.ItemRealValueModel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismPropertyValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismReferenceWrapperColumn.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismReferenceWrapperColumn.java index 4e4d88a5b46..a5694982a59 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismReferenceWrapperColumn.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismReferenceWrapperColumn.java @@ -13,11 +13,11 @@ import org.apache.wicket.model.Model; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismReferenceHeaderPanel; -import com.evolveum.midpoint.gui.impl.prism.PrismReferenceWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.impl.prism.panel.PrismReferenceHeaderPanel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismReferenceWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismReferenceValue; @@ -51,7 +51,17 @@ public IModel getDataModel(IModel> rowModel) { @Override protected Component createHeader(String componentId, IModel> mainModel) { - return new PrismReferenceHeaderPanel<>(componentId, new PrismReferenceWrapperHeaderModel(mainModel, itemName, pageBase)); + return new PrismReferenceHeaderPanel(componentId, new PrismReferenceWrapperHeaderModel(mainModel, itemName, pageBase)) { + @Override + protected boolean isAddButtonVisible() { + return false; + } + + @Override + protected boolean isButtonEnabled() { + return false; + } + }; } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismReferenceWrapperColumnPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismReferenceWrapperColumnPanel.java index be898b96844..9e3317a0bd0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismReferenceWrapperColumnPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/component/data/column/PrismReferenceWrapperColumnPanel.java @@ -13,12 +13,9 @@ import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.impl.component.data.column.AbstractItemWrapperColumn.ColumnType; import com.evolveum.midpoint.gui.impl.error.ErrorPanel; -import com.evolveum.midpoint.gui.impl.factory.ItemRealValueModel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismReferenceWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismReferenceWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.prism.Referencable; import com.evolveum.midpoint.util.exception.SchemaException; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ApprovalSchemaWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ApprovalSchemaWrapperFactoryImpl.java deleted file mode 100644 index ae2e03cb100..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ApprovalSchemaWrapperFactoryImpl.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.PrismContainer; -import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ApprovalSchemaType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -/** - * Created by Kate Honchar - */ -@Component -public class ApprovalSchemaWrapperFactoryImpl extends PrismContainerWrapperFactoryImpl { - - @Autowired - private GuiComponentRegistry registry; - - @Override - public boolean match(ItemDefinition def) { - return ApprovalSchemaType.COMPLEX_TYPE .equals(def.getTypeName()); - } - - @Override - public void register() { - registry.addToRegistry(this); - } - - @Override - public int getOrder() { - return 1000; - } - - @Override - protected PrismContainerValue createNewValue(PrismContainer item) { - throw new UnsupportedOperationException("New approval schema value should not be created while creating wrappers."); - } - - - @Override - protected boolean shouldCreateEmptyValue(PrismContainer item, WrapperContext context) { - return false; - } - -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/AssignmentWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/AssignmentWrapperFactoryImpl.java deleted file mode 100644 index dd21baed7e6..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/AssignmentWrapperFactoryImpl.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.PrismContainer; -import com.evolveum.midpoint.prism.PrismContainerDefinition; -import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.web.component.prism.ValueStatus; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; - -/** - * @author katka - * - */ -@Component -public class AssignmentWrapperFactoryImpl extends PrismContainerWrapperFactoryImpl { - - @Autowired private GuiComponentRegistry registry; - - @Override - public boolean match(ItemDefinition def) { - return def instanceof PrismContainerDefinition && def.isMultiValue(); - } - - @Override - public void register() { - registry.addToRegistry(this); - } - - @Override - public int getOrder() { - return 1000; - } - - @Override - protected PrismContainerValue createNewValue(PrismContainer item) { - throw new UnsupportedOperationException("New assignment value should not be created while creating wrappers."); - } - - - @Override - protected boolean shouldCreateEmptyValue(PrismContainer item, WrapperContext context) { - return false; - } - -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/CaseEventWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/CaseEventWrapperFactoryImpl.java deleted file mode 100644 index d3775fbb0b8..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/CaseEventWrapperFactoryImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.PrismContainer; -import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.web.component.prism.ValueStatus; -import com.evolveum.midpoint.xml.ns._public.common.common_3.CaseEventType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemCompletionEventType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemDelegationEventType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemEventType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -/** - * Created by honchar - */ -@Component -public class CaseEventWrapperFactoryImpl extends PrismContainerWrapperFactoryImpl { - - @Autowired - private GuiComponentRegistry registry; - - @Override - public boolean match(ItemDefinition def) { - return CaseEventType.COMPLEX_TYPE.equals(def.getTypeName()) || WorkItemEventType.COMPLEX_TYPE.equals(def.getTypeName()) || - WorkItemCompletionEventType.COMPLEX_TYPE.equals(def.getTypeName()) || WorkItemDelegationEventType.COMPLEX_TYPE.equals(def.getTypeName()); - } - - @Override - public void register() { - registry.addToRegistry(this); - } - - @Override - public int getOrder() { - return 1000; - } - - @Override - protected PrismContainerValue createNewValue(PrismContainer item) { - throw new UnsupportedOperationException("New case event value should not be created while creating wrappers."); - } - - - @Override - protected boolean shouldCreateEmptyValue(PrismContainer item, WrapperContext context) { - return false; - } - - @Override - public PrismContainerValueWrapper createValueWrapper(PrismContainerWrapper parent, - PrismContainerValue value, ValueStatus status, WrapperContext context) throws SchemaException { - context.setCreateIfEmpty(false); - return super.createValueWrapper(parent, value, status, context); - } - - -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/CaseWorkItemWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/CaseWorkItemWrapperFactoryImpl.java deleted file mode 100644 index 10bd9c8fa8d..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/CaseWorkItemWrapperFactoryImpl.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.CaseWorkItemTypeWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.PrismContainer; -import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.web.component.prism.ValueStatus; -import com.evolveum.midpoint.web.page.admin.workflow.WorkItemDetailsPanel; -import com.evolveum.midpoint.xml.ns._public.common.common_3.CaseWorkItemType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -/** - * Created by honchar - */ -@Component -public class CaseWorkItemWrapperFactoryImpl extends PrismContainerWrapperFactoryImpl { - - @Autowired - private GuiComponentRegistry registry; - - @Override - public boolean match(ItemDefinition def) { - return CaseWorkItemType.COMPLEX_TYPE.equals(def.getTypeName()); - } - - @Override - public void register() { - registry.addToRegistry(this); - } - - @Override - public int getOrder() { - return 1000; - } - - @Override - protected PrismContainerValue createNewValue(PrismContainer item) { - throw new UnsupportedOperationException("New case work item value should not be created while creating wrappers."); - } - - - @Override - protected boolean shouldCreateEmptyValue(PrismContainer item, WrapperContext context) { - return false; - } - - @Override - protected PrismContainerWrapper createWrapper(PrismContainerValueWrapper parent, PrismContainer item, - ItemStatus status, WrapperContext ctx) { - getRegistry().registerWrapperPanel(item.getDefinition().getTypeName(), WorkItemDetailsPanel.class); - CaseWorkItemTypeWrapper containerWrapper = new CaseWorkItemTypeWrapper(parent, item, status); - return containerWrapper; - } - - @Override - public PrismContainerValueWrapper createValueWrapper(PrismContainerWrapper parent, - PrismContainerValue value, ValueStatus status, WrapperContext context) throws SchemaException { - context.setCreateIfEmpty(false); - return super.createValueWrapper(parent, value, status, context); - } - - -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ExpressionWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ExpressionWrapperFactory.java deleted file mode 100644 index b4272f8e8cd..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ExpressionWrapperFactory.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.impl.prism.*; -import com.evolveum.midpoint.gui.impl.prism.component.ExpressionPropertyPanel; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.PrismProperty; -import com.evolveum.midpoint.prism.path.ItemName; -import com.evolveum.midpoint.util.QNameUtil; -import com.evolveum.midpoint.gui.impl.prism.ExpressionWrapper; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.MappingType; -import net.sf.jasperreports.olap.mapping.Mapping; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * Created by honchar - */ -@Component -public class ExpressionWrapperFactory extends PrismPropertyWrapperFactoryImpl { - - @Override - public boolean match(ItemDefinition def) { - return QNameUtil.match(ExpressionType.COMPLEX_TYPE, def.getTypeName()); - } - - @PostConstruct - @Override - public void register() { - getRegistry().addToRegistry(this); - } - - @Override - public int getOrder() { - return 100; - } - - @Override - protected PrismPropertyWrapper createWrapper(PrismContainerValueWrapper parent, PrismProperty item, - ItemStatus status, WrapperContext ctx) { - - ExpressionWrapper propertyWrapper = new ExpressionWrapper(parent, item, status); - if (propertyWrapper.isConstructionExpression() || propertyWrapper.isAttributeExpression() || propertyWrapper.isAssociationExpression()) { - getRegistry().registerWrapperPanel(propertyWrapper.getTypeName(), ExpressionPropertyPanel.class); - } else { - return super.createWrapper(parent, item, status, ctx); - } - return propertyWrapper; - } - -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/HeterogenousContainerWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/HeterogenousContainerWrapperFactory.java deleted file mode 100644 index 0d919aadec7..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/HeterogenousContainerWrapperFactory.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import javax.annotation.PostConstruct; -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskPartitionDefinitionType; - -import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskPartitionsDefinitionType; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerPanel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapperImpl; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerWrapperImpl; -import com.evolveum.midpoint.prism.Containerable; -import com.evolveum.midpoint.prism.Item; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.PrismContainer; -import com.evolveum.midpoint.prism.PrismContainerDefinition; -import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.prism.path.ItemName; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.prism.ValueStatus; - -/** - * @author katka - */ -@Component -public class HeterogenousContainerWrapperFactory implements PrismContainerWrapperFactory { - - private static final Trace LOGGER = TraceManager.getTrace(HeterogenousContainerWrapperFactory.class); - - @Autowired private GuiComponentRegistry registry; - - @Override - public PrismContainerWrapper createWrapper(PrismContainerValueWrapper parent, - ItemDefinition def, WrapperContext context) throws SchemaException { - ItemName name = def.getItemName(); - - PrismContainer childItem = parent.getNewValue().findContainer(name); - ItemStatus status = ItemStatus.NOT_CHANGED; - if (childItem == null) { - childItem = (PrismContainer)parent.getNewValue().findOrCreateContainer(name); - status = ItemStatus.ADDED; - } - - PrismContainerWrapper itemWrapper = new PrismContainerWrapperImpl(parent, childItem, status); - registry.registerWrapperPanel(childItem.getDefinition().getTypeName(), PrismContainerPanel.class); - - List> valueWrappers = createValuesWrapper(itemWrapper, childItem, context); - LOGGER.trace("valueWrappers {}", itemWrapper.getValues()); - itemWrapper.getValues().addAll((Collection) valueWrappers); - - return itemWrapper; - } - - @Override - public PrismContainerValueWrapper createValueWrapper(PrismContainerWrapper parent, - PrismContainerValue value, ValueStatus status, WrapperContext context) - throws SchemaException { - PrismContainerValueWrapper containerValueWrapper = new PrismContainerValueWrapperImpl(parent, value, status); - containerValueWrapper.setShowEmpty(context.isShowEmpty()); - containerValueWrapper.setExpanded(shouldBeExpanded(parent, value, context)); - containerValueWrapper.setHeterogenous(true); - - List> wrappers = new ArrayList<>(); - - for (ItemDefinition def : value.getDefinition().getDefinitions()) { - - Item childItem = value.findItem(def.getItemName()); - - if (childItem == null && def instanceof PrismContainerDefinition) { - LOGGER.trace("Skipping creating wrapper for {}, only property and reference wrappers are created for heterogeneous containers.", def); - continue; - } - - ItemWrapperFactory factory = registry.findWrapperFactory(def); - - ItemWrapper wrapper = factory.createWrapper(containerValueWrapper, def, context); - if (wrapper != null) { - wrappers.add(wrapper); - } - } - - containerValueWrapper.getItems().addAll((Collection) wrappers); - return containerValueWrapper; - } - - protected boolean shouldBeExpanded(PrismContainerWrapper parent, PrismContainerValue value, WrapperContext context) { - if (value.isEmpty()) { - return context.isShowEmpty() || containsEmphasizedItems(parent.getDefinitions()); - } - - return true; - } - - private boolean containsEmphasizedItems(List definitions) { - for (ItemDefinition def : definitions) { - if (def.isEmphasized()) { - return true; - } - } - - return false; - } - - protected List> createValuesWrapper(PrismContainerWrapper itemWrapper, PrismContainer item, WrapperContext context) throws SchemaException { - List> pvWrappers = new ArrayList<>(); - - if (item.getValues() == null || item.getValues().isEmpty()) { - PrismContainerValueWrapper valueWrapper = createValueWrapper(itemWrapper, item.createNewValue(), ValueStatus.ADDED, context); - pvWrappers.add(valueWrapper); - return pvWrappers; - } - - for (PrismContainerValue pcv : item.getValues()) { - PrismContainerValueWrapper valueWrapper = createValueWrapper(itemWrapper, pcv, ValueStatus.NOT_CHANGED, context); - pvWrappers.add(valueWrapper); - } - - return pvWrappers; - - } - - /** - * - * match single value containers which contains a looot of other conainers, e.g. policy rule, policy action, notification configuration, etc - */ - @Override - public boolean match(ItemDefinition def) { - QName defName = def.getTypeName(); - - if (TaskPartitionsDefinitionType.COMPLEX_TYPE.equals(defName)) { - return true; - } - - if (!(def instanceof PrismContainerDefinition)) { - return false; - } - - PrismContainerDefinition containerDef = (PrismContainerDefinition) def; - - if (containerDef.isMultiValue()) { - return false; - } - - List defs = containerDef.getDefinitions(); - int containers = 0; - for (ItemDefinition itemDef : defs) { - if (itemDef instanceof PrismContainerDefinition && itemDef.isMultiValue()) { - containers++; - } - } - - if (containers > 2) { - return true; - } - - return false; - -// if (def.isSingleValue() && ) -// return PolicyConstraintPresentationType.COMPLEX_TYPE.equals(defName) -// || StatePolicyConstraintType.COMPLEX_TYPE.equals(defName) -// || HasAssignmentPolicyConstraintType.COMPLEX_TYPE.equals(defName) -// || ExclusionPolicyConstraintType.COMPLEX_TYPE.equals(defName) -// || PolicyConstraintsType.COMPLEX_TYPE.equals(defName); - } - - @Override - @PostConstruct - public void register() { - registry.addToRegistry(this); - } - - @Override - public int getOrder() { - return 110; - } - - @Override - public PrismContainerValueWrapper createContainerValueWrapper(PrismContainerWrapper objectWrapper, - PrismContainerValue objectValue, ValueStatus status, WrapperContext context) { - // TODO Auto-generated method stub - return null; - } - - @Override - public PrismContainerWrapper createWrapper(Item childContainer, ItemStatus status, WrapperContext context) - throws SchemaException { - // TODO Auto-generated method stub - return null; - } - - -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/LoggingAppenderWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/LoggingAppenderWrapperFactoryImpl.java deleted file mode 100644 index 67bebef65d7..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/LoggingAppenderWrapperFactoryImpl.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import java.util.List; - -import org.springframework.stereotype.Component; - -import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyPanel; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapperImpl; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.PrismProperty; -import com.evolveum.midpoint.prism.PrismPropertyDefinition; -import com.evolveum.midpoint.util.QNameUtil; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AppenderConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ClassLoggerConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LoggingConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableRowType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; -import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; - -/** - * @author skublik - * - */ -@Component -public class LoggingAppenderWrapperFactoryImpl extends PrismPropertyWrapperFactoryImpl{ - - @Override - public boolean match(ItemDefinition def) { - return def instanceof PrismPropertyDefinition - && QNameUtil.match(def.getItemName(), ClassLoggerConfigurationType.F_APPENDER); - } - - @Override - public int getOrder() { - return Integer.MAX_VALUE-1; - } - - @Override - protected PrismPropertyWrapper createWrapper(PrismContainerValueWrapper parent, PrismProperty item, - ItemStatus status, WrapperContext ctx) { - getRegistry().registerWrapperPanel(item.getDefinition().getTypeName(), PrismPropertyPanel.class); - PrismPropertyWrapper propertyWrapper = new PrismPropertyWrapperImpl<>(parent, item, status); - propertyWrapper.setPredefinedValues(getPredefinedValues(parent)); - return propertyWrapper; - } - - private LookupTableType getPredefinedValues(PrismContainerValueWrapper parent) { - LookupTableType lookupTable = new LookupTableType(); - List list = lookupTable.createRowList(); - - if(parent == null || parent.getParent() == null || parent.getParent().getParent() == null) { - return lookupTable; - } - - - if(!(parent.getParent().getParent().getRealValue() instanceof LoggingConfigurationType)) { - throw new IllegalArgumentException("LoggingConfigurationType not found in parent for Appender"); - } - - LoggingConfigurationType loggingConfig = (LoggingConfigurationType) parent.getParent().getParent().getRealValue(); - - for (AppenderConfigurationType appender : loggingConfig.getAppender()) { - LookupTableRowType row = new LookupTableRowType(); - String name = appender.getName(); - row.setKey(name); - row.setValue(name); - row.setLabel(new PolyStringType(name)); - list.add(row); - } - return lookupTable; - } - -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/LoggingConfigurationWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/LoggingConfigurationWrapperFactoryImpl.java deleted file mode 100644 index d8a02c62380..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/LoggingConfigurationWrapperFactoryImpl.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import javax.annotation.PostConstruct; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerPanel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapperImpl; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerWrapperImpl; -import com.evolveum.midpoint.prism.*; -import com.evolveum.midpoint.util.QNameUtil; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.prism.ValueStatus; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ClassLoggerConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LoggingConfigurationType; - -/** - * @author skublik - */ -@Component -public class LoggingConfigurationWrapperFactoryImpl extends PrismContainerWrapperFactoryImpl{ - - @Autowired - private ClassLoggerWrapperFactoryImpl classLoggerFactory; - @Autowired - private ProfilingClassLoggerWrapperFactoryImpl profilingClassLoggerFactory; - @Autowired private GuiComponentRegistry registry; - - @Override - public boolean match(ItemDefinition def) { - return def instanceof PrismContainerDefinition - && QNameUtil.match(def.getTypeName(), LoggingConfigurationType.COMPLEX_TYPE); - } - - @PostConstruct - @Override - public void register() { - registry.addToRegistry(this); - } - - /* (non-Javadoc) - * @see com.evolveum.midpoint.gui.impl.factory.WrapperFactory#getOrder() - */ - @Override - public int getOrder() { - return 10; - } - - - /* (non-Javadoc) - * @see com.evolveum.midpoint.gui.impl.factory.ItemWrapperFactory#createValueWrapper(com.evolveum.midpoint.prism.PrismValue, com.evolveum.midpoint.web.component.prism.ValueStatus, com.evolveum.midpoint.gui.impl.factory.WrapperContext) - */ - @Override - public PrismContainerValueWrapper createValueWrapper(PrismContainerWrapper parent, PrismContainerValue value, ValueStatus status, WrapperContext context) - throws SchemaException { - PrismContainerValueWrapper containerValueWrapper = createContainerValueWrapper(parent, value, status, context); - containerValueWrapper.setExpanded(!value.isEmpty()); - - - List> wrappers = new ArrayList<>(); - for (ItemDefinition def : parent.getDefinitions()) { - if (QNameUtil.match(def.getTypeName(), ClassLoggerConfigurationType.COMPLEX_TYPE)) { - wrappers.add(createClassLoggingWrapper(containerValueWrapper, def, context)); - wrappers.add(createProfilingWrapper(containerValueWrapper, def, context)); - } else { - super.addItemWrapper(def, containerValueWrapper, context, wrappers); - } - } - - containerValueWrapper.getItems().addAll((Collection) wrappers); - return containerValueWrapper; - } - - private ItemWrapper createProfilingWrapper(PrismContainerValueWrapper parent, ItemDefinition def, WrapperContext context) throws SchemaException { - return profilingClassLoggerFactory.createWrapper(parent, def, context); - } - - private ItemWrapper createClassLoggingWrapper(PrismContainerValueWrapper parent, ItemDefinition def, WrapperContext context) throws SchemaException { - return classLoggerFactory.createWrapper(parent, def, context); - } - - @Override - protected PrismContainerValue createNewValue(PrismContainer item) { - return item.createNewValue(); - } - - @Override - protected PrismContainerWrapper createWrapper(PrismContainerValueWrapper parent, PrismContainer childContainer, - ItemStatus status, WrapperContext ctx) { - registry.registerWrapperPanel(childContainer.getDefinition().getTypeName(), PrismContainerPanel.class); - return new PrismContainerWrapperImpl<>(parent, childContainer, status); - } - - @Override - public PrismContainerValueWrapper createContainerValueWrapper(PrismContainerWrapper objectWrapper, PrismContainerValue objectValue, ValueStatus status, WrapperContext context) { - return new PrismContainerValueWrapperImpl(objectWrapper, objectValue, status); - } - - -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/MetadataWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/MetadataWrapperFactory.java deleted file mode 100644 index 26b455e8c57..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/MetadataWrapperFactory.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import java.util.List; - -import javax.annotation.PostConstruct; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.util.QNameUtil; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.xml.ns._public.common.common_3.MetadataType; - -/** - * @author katka - * - */ -@Component -public class MetadataWrapperFactory extends PrismContainerWrapperFactoryImpl{ - - - @Autowired private GuiComponentRegistry registry; - - @Override - public boolean match(ItemDefinition def) { - return QNameUtil.match(MetadataType.COMPLEX_TYPE, def.getTypeName()); - } - - @PostConstruct - @Override - public void register() { - registry.addToRegistry(this); - } - - @Override - public int getOrder() { - return 10; - } - - protected void addItemWrapper(ItemDefinition def, PrismContainerValueWrapper containerValueWrapper, - WrapperContext context, List> wrappers) throws SchemaException { - - ItemWrapperFactory factory = registry.findWrapperFactory(def); - - context.setCreateOperational(true); - ItemWrapper wrapper = factory.createWrapper(containerValueWrapper, def, context); - wrapper.setReadOnly(true); - wrappers.add(wrapper); - context.setCreateOperational(false); - } - - @Override - protected boolean canCreateWrapper(ItemDefinition def, ItemStatus status, WrapperContext context, boolean isEmptyValue) { - return true; - } -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PolyStringEditorPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PolyStringEditorPanelFactory.java deleted file mode 100644 index e361fe872ad..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PolyStringEditorPanelFactory.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.prism.polystring.PolyString; -import com.evolveum.midpoint.gui.impl.prism.component.PolyStringEditorPanel; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; -import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; -import org.apache.wicket.markup.html.panel.Panel; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import java.util.Iterator; -import java.util.List; - -/** - * Created by honchar - */ -@Component -public class PolyStringEditorPanelFactory extends AbstractGuiComponentFactory { - - private static final long serialVersionUID = 1L; - - @Autowired - GuiComponentRegistry registry; - - @PostConstruct - public void register() { - registry.addToRegistry(this); - } - @Override - public boolean match(IW wrapper) { - return PolyStringType.COMPLEX_TYPE.equals(wrapper.getTypeName()); - } - - @Override - protected Panel getPanel(PrismPropertyPanelContext panelCtx) { - return new PolyStringEditorPanel(panelCtx.getComponentId(), panelCtx.getRealValueModel(), - panelCtx.getPredefinedValues(), panelCtx.hasValueEnumerationRef()); - } - -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismContainerWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismContainerWrapperFactory.java deleted file mode 100644 index b9975948eec..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismContainerWrapperFactory.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import java.util.List; - -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.prism.Containerable; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.web.component.prism.ValueStatus; - -/** - * @author katka - * - */ -public interface PrismContainerWrapperFactory extends ItemWrapperFactory, PrismContainerValueWrapper, PrismContainerValue>{ - - - PrismContainerValueWrapper createContainerValueWrapper(PrismContainerWrapper objectWrapper, PrismContainerValue objectValue, ValueStatus status, WrapperContext context); - - -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismObjectWrapperBuilder.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismObjectWrapperBuilder.java deleted file mode 100644 index ef0ee33cd3e..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismObjectWrapperBuilder.java +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -/** - * @author katka - * - */ -public class PrismObjectWrapperBuilder { - -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ProfilingClassLoggerWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ProfilingClassLoggerWrapperFactoryImpl.java deleted file mode 100644 index 757d2e2df4e..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ProfilingClassLoggerWrapperFactoryImpl.java +++ /dev/null @@ -1,101 +0,0 @@ -/* -\ * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.namespace.QName; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.ProfilingClassLoggerContainerValueWrapperImpl; -import com.evolveum.midpoint.gui.impl.prism.ProfilingClassLoggerContainerWrapperImpl; -import com.evolveum.midpoint.gui.impl.prism.ProfilingClassLoggerPanel; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.PrismContainer; -import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.web.component.prism.ValueStatus; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ClassLoggerConfigurationType; - -/** - * @author skublik - */ -@Component -public class ProfilingClassLoggerWrapperFactoryImpl extends PrismContainerWrapperFactoryImpl { - - @Autowired private GuiComponentRegistry registry; - - public static final QName PROFILING_LOGGER_PATH = new QName("profilingClassLogger"); - - public static final String LOGGER_PROFILING = "PROFILING"; - - @Override - public boolean match(ItemDefinition def) { - return false; - } - - @Override - protected boolean canCreateValueWrapper(PrismContainerValue value) { - if(value == null || value.getRealValue() == null) { - return false; - } - String loggerPackage = ((ClassLoggerConfigurationType)value.getRealValue()).getPackage(); - if(loggerPackage == null) { - return false; - } - return loggerPackage.equals(LOGGER_PROFILING); - } - - @Override - protected PrismContainerWrapper createWrapper(PrismContainerValueWrapper parent, - PrismContainer childContainer, ItemStatus status, WrapperContext ctx) { - PrismContainer clone = childContainer.clone(); -// clone.setElementName(PROFILING_LOGGER_PATH); - registry.registerWrapperPanel(PROFILING_LOGGER_PATH, ProfilingClassLoggerPanel.class); - return new ProfilingClassLoggerContainerWrapperImpl<>(parent, clone, status); - } - - @Override - protected >> List> createValuesWrapper( - PrismContainerWrapper itemWrapper, PrismContainer item, WrapperContext context) - throws SchemaException { - List> pvWrappers = new ArrayList<>(); - - for (PrismContainerValue pcv : item.getValues()) { - if(canCreateValueWrapper(pcv)) { - PrismContainerValueWrapper valueWrapper = createValueWrapper(itemWrapper, pcv, ValueStatus.NOT_CHANGED, context); - pvWrappers.add(valueWrapper); - } - } - - if (pvWrappers.isEmpty()) { - PrismContainerValue prismValue = createNewValue(item); - PrismContainerValueWrapper valueWrapper = createValueWrapper(itemWrapper, prismValue, ValueStatus.ADDED, context); - valueWrapper.getRealValue().setPackage(LOGGER_PROFILING); - pvWrappers.add(valueWrapper); - } - - return pvWrappers; - } - - @Override - public PrismContainerValueWrapper createContainerValueWrapper(PrismContainerWrapper objectWrapper, - PrismContainerValue objectValue, ValueStatus status, WrapperContext context) { - - ClassLoggerConfigurationType logger = objectValue.getRealValue(); - logger.setPackage(LOGGER_PROFILING); - - return new ProfilingClassLoggerContainerValueWrapperImpl(objectWrapper, objectValue, status); - } - -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ShadowAssociationWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ShadowAssociationWrapperFactoryImpl.java deleted file mode 100644 index 07f0cfe6be3..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ShadowAssociationWrapperFactoryImpl.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.evolveum.midpoint.common.refinery.RefinedAssociationDefinition; -import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; -import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; -import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.impl.prism.*; -import com.evolveum.midpoint.model.api.ModelService; -import com.evolveum.midpoint.prism.*; -import com.evolveum.midpoint.prism.path.ItemName; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.task.api.TaskManager; -import com.evolveum.midpoint.util.QNameUtil; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.prism.ValueStatus; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; - -/** - * @author skublik - */ -@Component -public class ShadowAssociationWrapperFactoryImpl extends PrismContainerWrapperFactoryImpl { - - private static final Trace LOGGER = TraceManager.getTrace(ShadowAssociationWrapperFactoryImpl.class); - - @Autowired private GuiComponentRegistry registry; - @Autowired private PrismContext prismContext; - @Autowired private ModelService modelService; - @Autowired private TaskManager taskManager; - - private static final String CREATE_ASSOCIATION_WRAPPER = "createAssociationWrapper"; - - @Override - public boolean match(ItemDefinition def) { - return QNameUtil.match(def.getTypeName(), ShadowAssociationType.COMPLEX_TYPE); - } - - @Override - public int getOrder() { - return 10; - } - - @Override - public PrismContainerWrapper createWrapper(PrismContainerValueWrapper parent, ItemDefinition def, - WrapperContext context) throws SchemaException { - ItemName name = def.getItemName(); - - PrismContainer childItem = (PrismContainer) parent.getNewValue().findItem(name); - ItemStatus status = ItemStatus.NOT_CHANGED; - if (childItem == null) { - childItem = (PrismContainer) parent.getNewValue().findOrCreateItem(name); - status = ItemStatus.ADDED; - } - - PrismContainerWrapper itemWrapper = createWrapper(parent, childItem, status, context); - itemWrapper.setShowEmpty(context.isCreateIfEmpty(), false); - return itemWrapper; - } - - protected PrismContainerWrapper createWrapper(PrismContainerValueWrapper parent, PrismContainer childContainer, - ItemStatus status, WrapperContext ctx) { - - try { - ObjectType objectType = (ObjectType) parent.getRealValue(); - ShadowType shadow; - if (objectType instanceof ShadowType) { - shadow = (ShadowType) objectType; - } else { - throw new SchemaException("Something very strange happened. Association container in the " + objectType.getClass().getSimpleName() + "?"); - } - - if (shadow.getResourceRef().getOid() == null) { - return super.createWrapper(parent, childContainer, status, ctx); - } - Task task = taskManager.createTaskInstance("Load resource ref"); - OperationResult result = task.getResult(); - PrismObject resource = modelService.getObject(ResourceType.class, shadow.getResourceRef().getOid(), null, task, result); - - result.computeStatusIfUnknown(); - if (!result.isAcceptable()) { - LOGGER.error("Cannot find resource referenced from shadow. {}", result.getMessage()); - result.recordPartialError("Could not find resource referenced from shadow."); - return super.createWrapper(parent, childContainer, status, ctx); - } - - ShadowKindType kind = shadow.getKind(); - String shadowIntent = shadow.getIntent(); - PrismContainer association = childContainer; - - if (association == null || association.getDefinition() == null - || (!(association.getDefinition().getCompileTimeClass().equals(ShadowAssociationType.class)) - && !(association.getDefinition().getCompileTimeClass().equals(ResourceObjectAssociationType.class)))) { - LOGGER.debug("Association for {} is not supported", association.getComplexTypeDefinition().getTypeClass()); - return super.createWrapper(parent, childContainer, status, ctx); - } - result = new OperationResult(CREATE_ASSOCIATION_WRAPPER); - //we need to switch association wrapper to single value - //the transformation will be as following: - // we have single value ShadowAssociationType || ResourceObjectAssociationType, and from each shadowAssociationType we will create - // property - name of the property will be association type(QName) and the value will be shadowRef - PrismContainerDefinition associationDefinition = association.getDefinition().clone(); - associationDefinition.toMutable().setMaxOccurs(1); - - RefinedResourceSchema refinedResourceSchema = RefinedResourceSchema.getRefinedSchema(resource); - RefinedObjectClassDefinition oc = refinedResourceSchema.getRefinedDefinition(kind, shadowIntent); - if (oc == null) { - LOGGER.debug("Association for {}/{} not supported by resource {}", kind, shadowIntent, resource); - return super.createWrapper(parent, childContainer, status, ctx); - } - Collection refinedAssociationDefinitions = oc.getAssociationDefinitions(); - - if (CollectionUtils.isEmpty(refinedAssociationDefinitions)) { - LOGGER.debug("Association for {}/{} not supported by resource {}", kind, shadowIntent, resource); - return super.createWrapper(parent, childContainer, status, ctx); - } - - PrismContainer associationTransformed = associationDefinition.instantiate(); - PrismContainerWrapper associationWrapper; - if (association.getDefinition().getCompileTimeClass().equals(ShadowAssociationType.class)) { - registry.registerWrapperPanel(associationTransformed.getDefinition().getTypeName(), PrismContainerPanel.class); - associationWrapper = new ShadowAssociationWrapperImpl((PrismContainerValueWrapper) parent, associationTransformed, status); - } else { - return super.createWrapper(parent, childContainer, status, ctx); - } - - WrapperContext context = new WrapperContext(task, result); - context.setShowEmpty(ItemStatus.ADDED == status); - PrismContainerValueWrapper shadowValueWrapper = createContainerValueWrapper(associationWrapper, - associationTransformed.createNewValue(), - ItemStatus.ADDED == status ? ValueStatus.ADDED : ValueStatus.NOT_CHANGED, context); - - List> items = new ArrayList<>(); - for (RefinedAssociationDefinition refinedAssociationDefinition : refinedAssociationDefinitions) { - MutablePrismReferenceDefinition shadowRefDef = prismContext - .definitionFactory().createReferenceDefinition(refinedAssociationDefinition.getName(), ObjectReferenceType.COMPLEX_TYPE); - shadowRefDef.toMutable().setMaxOccurs(-1); - shadowRefDef.setTargetTypeName(ShadowType.COMPLEX_TYPE); - PrismReference shadowAss = shadowRefDef.instantiate(); - ItemPath itemPath = null; - for (PrismContainerValue associationValue : association.getValues()) { - if (association.getDefinition().getCompileTimeClass().equals(ShadowAssociationType.class)) { - ShadowAssociationType shadowAssociation = (ShadowAssociationType) associationValue.asContainerable(); - if (shadowAssociation.getName().equals(refinedAssociationDefinition.getName())) { - itemPath = associationValue.getPath(); - shadowAss.add(associationValue.findReference(ShadowAssociationType.F_SHADOW_REF).getValue().clone()); - } - } - } - - if (itemPath == null) { - itemPath = ShadowType.F_ASSOCIATION; - } - - String displayName = refinedAssociationDefinition.getDisplayName(); - if (StringUtils.isBlank(displayName)) { - displayName = refinedAssociationDefinition.getName().getLocalPart(); - } - - ShadowAssociationReferenceWrapperImpl item = new ShadowAssociationReferenceWrapperImpl(shadowValueWrapper, shadowAss, - shadowAss.isEmpty() ? ItemStatus.ADDED : ItemStatus.NOT_CHANGED); - item.setDisplayName(displayName); - List refValues = new ArrayList(); - for (PrismReferenceValue prismValue : shadowAss.getValues()) { - PrismReferenceValueWrapperImpl refValue = new PrismReferenceValueWrapperImpl(item, prismValue, - prismValue.isEmpty() ? ValueStatus.ADDED : ValueStatus.NOT_CHANGED); - refValue.setEditEnabled(isEmpty(prismValue)); - refValues.add(refValue); - } - if (shadowAss.getValues().isEmpty()) { - PrismReferenceValue prismReferenceValue = getPrismContext().itemFactory().createReferenceValue(); - shadowAss.add(prismReferenceValue); - PrismReferenceValueWrapperImpl refValue = new PrismReferenceValueWrapperImpl(item, prismReferenceValue, - shadowAss.getValue().isEmpty() ? ValueStatus.ADDED : ValueStatus.NOT_CHANGED); - refValue.setEditEnabled(true); - refValues.add(refValue); - } - item.getValues().addAll((Collection) refValues); - item.setFilter(WebComponentUtil.createAssociationShadowRefFilter(refinedAssociationDefinition, - prismContext, resource.getOid())); -// item.setReadOnly(true); - - items.add(item); - } - shadowValueWrapper.setExpanded(true); - shadowValueWrapper.getItems().addAll((Collection) items); - associationWrapper.getValues().addAll(Arrays.asList(shadowValueWrapper)); - return associationWrapper; - } catch (Exception e) { - LOGGER.error("Couldn't create container for associations. ", e); - } - return null; - } - - private boolean isEmpty(PrismReferenceValue prismValue) { - if (prismValue == null) { - return true; - } - - return prismValue.isEmpty(); - } -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TaskHandlerWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TaskHandlerWrapperFactory.java deleted file mode 100644 index 6ebc60775ed..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TaskHandlerWrapperFactory.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2010-2020 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyPanel; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapperImpl; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismProperty; -import com.evolveum.midpoint.prism.PrismReferenceValue; -import com.evolveum.midpoint.schema.GetOperationOptions; -import com.evolveum.midpoint.schema.SelectorOptions; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.QNameUtil; -import com.evolveum.midpoint.util.exception.*; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; - -import com.evolveum.prism.xml.ns._public.types_3.PolyStringTranslationType; -import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; - -import org.apache.commons.lang.StringUtils; -import org.springframework.stereotype.Component; - -import java.util.Collection; -import java.util.stream.Collectors; - -@Component -public class TaskHandlerWrapperFactory extends PrismPropertyWrapperFactoryImpl { - - private static final transient Trace LOGGER = TraceManager.getTrace(TaskHandlerWrapperFactory.class); - - private static final String OPERATION_DETERMINE_LOOKUP_TABLE = "determineLookupTable"; - - @Override - protected PrismPropertyWrapper createWrapper(PrismContainerValueWrapper parent, PrismProperty item, - ItemStatus status, WrapperContext ctx) { - - PrismObject prismObject = getParent(ctx); - if (prismObject == null || !TaskType.class.equals(prismObject.getCompileTimeClass())) { - return super.createWrapper(parent, item, status, ctx); - } - - getRegistry().registerWrapperPanel(item.getDefinition().getTypeName(), PrismPropertyPanel.class); - PrismPropertyWrapper propertyWrapper = new PrismPropertyWrapperImpl<>(parent, item, status); - PrismReferenceValue valueEnumerationRef = item.getDefinition().getValueEnumerationRef(); - if (valueEnumerationRef != null) { - Task task = ctx.getTask(); - OperationResult result = ctx.getResult().createSubresult(OPERATION_DETERMINE_LOOKUP_TABLE); - Collection> options = WebModelServiceUtils - .createLookupTableRetrieveOptions(schemaHelper); - - try { - PrismObject lookupTable = modelService.getObject(LookupTableType.class, valueEnumerationRef.getOid(), options, task, result); - propertyWrapper.setPredefinedValues(lookupTable.asObjectable()); - } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | CommunicationException - | ConfigurationException | ExpressionEvaluationException e) { - LOGGER.error("Cannot load lookup table for {} ", item); - //TODO throw??? - } - - return propertyWrapper; - } - - if (parent != null && parent.getParent() != null) { - - TaskType task = (TaskType) prismObject.asObjectable(); - - if (ItemStatus.ADDED == status) { - Collection assignmentTypes = task.getAssignment() - .stream() - .filter(assignmentType -> WebComponentUtil.isArchetypeAssignment(assignmentType)) - .collect(Collectors.toList()); - - Collection handlers; - if (assignmentTypes.isEmpty()) { - // TODO all handlers - handlers = taskManager.getAllHandlerUris(true); - } else if (assignmentTypes.size() == 1) { - AssignmentType archetypeAssignment = assignmentTypes.iterator().next(); - handlers = taskManager.getHandlerUrisForArchetype(archetypeAssignment.getTargetRef().getOid(), true); - } else { - throw new UnsupportedOperationException("More than 1 archetype, this is not supported"); - } - LookupTableType lookupTableType = new LookupTableType(getPrismContext()); - - handlers.forEach(handler -> { - LookupTableRowType row = new LookupTableRowType(getPrismContext()); - row.setKey(handler); - handler = normalizeHandler(handler); - PolyStringType handlerLabel = new PolyStringType(handler); - PolyStringTranslationType translation = new PolyStringTranslationType(); - translation.setKey(handler); - handlerLabel.setTranslation(translation); - row.setLabel(handlerLabel); - lookupTableType.getRow().add(row); - }); - - propertyWrapper.setPredefinedValues(lookupTableType); - - } - } - return propertyWrapper; - } - - private PrismObject getParent(WrapperContext ctx) { - return ctx.getObject(); - } - - private String normalizeHandler(String handler) { - handler = StringUtils.remove(handler, "-3"); - handler = StringUtils.removeStart(handler, "http://midpoint.evolveum.com/xml/ns/public/").replace("-", "/").replace("#", "/"); - String[] split = handler.split("/"); - handler = "TaskHandlerSelector." + StringUtils.join(split, "."); - return handler; - } - - - @Override - public int getOrder() { - return super.getOrder() - 10; - } - - @Override - public boolean match(ItemDefinition def) { - return TaskType.F_HANDLER_URI.equivalent(def.getItemName()); - } -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ThreeStateComboPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ThreeStateComboPanelFactory.java deleted file mode 100644 index a01419e8924..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ThreeStateComboPanelFactory.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import javax.annotation.PostConstruct; - -import org.apache.wicket.markup.html.panel.Panel; -import org.apache.wicket.model.IModel; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.util.DOMUtil; -import com.evolveum.midpoint.web.component.input.TriStateComboPanel; - -/** - * @author katka - * - */ -@Component -public class ThreeStateComboPanelFactory extends AbstractGuiComponentFactory { - - private static final long serialVersionUID = 1L; - - @Autowired private GuiComponentRegistry registry; - - @PostConstruct - public void register() { - registry.addToRegistry(this); - } - @Override - public boolean match(IW wrapper) { - return DOMUtil.XSD_BOOLEAN.equals(wrapper.getTypeName()); - } - - @Override - protected Panel getPanel(PrismPropertyPanelContext panelCtx) { - return new TriStateComboPanel(panelCtx.getComponentId(), (IModel) panelCtx.getRealValueModel()); - } - - - -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TriggerTypeWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TriggerTypeWrapperFactory.java deleted file mode 100644 index d64c0e0ced5..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TriggerTypeWrapperFactory.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import java.util.List; - -import javax.annotation.PostConstruct; - -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.prism.PrismContainer; -import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.web.component.prism.ValueStatus; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TriggerType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.util.QNameUtil; -import com.evolveum.midpoint.util.exception.SchemaException; - -/** - * @author Kate Honchar - * - */ -@Component -public class TriggerTypeWrapperFactory extends PrismContainerWrapperFactoryImpl{ - - - @Autowired - private GuiComponentRegistry registry; - - @Override - public boolean match(ItemDefinition def) { - return QNameUtil.match(TriggerType.COMPLEX_TYPE, def.getTypeName()); - } - - @PostConstruct - @Override - public void register() { - registry.addToRegistry(this); - } - - @Override - public int getOrder() { - return 10; - } - - protected void addItemWrapper(ItemDefinition def, PrismContainerValueWrapper containerValueWrapper, - WrapperContext context, List> wrappers) throws SchemaException { - ItemWrapperFactory factory = registry.findWrapperFactory(def); - context.setCreateOperational(true); - ItemWrapper wrapper = factory.createWrapper(containerValueWrapper, def, context); - wrapper.setReadOnly(true); - wrappers.add(wrapper); - context.setCreateOperational(false); - } - - @Override - protected boolean canCreateWrapper(ItemDefinition def, ItemStatus status, WrapperContext context, boolean isEmptyValue) { - return true; - } - - @Override - protected boolean shouldCreateEmptyValue(PrismContainer item, WrapperContext context) { - return false; - } - - - @Override - public PrismContainerValueWrapper createValueWrapper(PrismContainerWrapper parent, - PrismContainerValue value, ValueStatus status, WrapperContext context) throws SchemaException { - context.setCreateIfEmpty(false); - return super.createValueWrapper(parent, value, status, context); - } - -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/WorkItemOutputWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/WorkItemOutputWrapperFactoryImpl.java deleted file mode 100644 index 1f43a19f040..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/WorkItemOutputWrapperFactoryImpl.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.PrismContainer; -import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.web.component.prism.ValueStatus; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -/** - * Created by honchar - */ -@Component -public class WorkItemOutputWrapperFactoryImpl extends PrismContainerWrapperFactoryImpl { - - @Autowired - private GuiComponentRegistry registry; - - @Override - public boolean match(ItemDefinition def) { - return AbstractWorkItemOutputType.COMPLEX_TYPE.equals(def.getTypeName()); - } - - @Override - public void register() { - registry.addToRegistry(this); - } - - @Override - public int getOrder() { - return 1000; - } - - @Override - protected PrismContainerValue createNewValue(PrismContainer item) { - throw new UnsupportedOperationException("New work item output value should not be created while creating wrappers."); - } - - - @Override - protected boolean shouldCreateEmptyValue(PrismContainer item, WrapperContext context) { - return false; - } - - @Override - public PrismContainerValueWrapper createValueWrapper(PrismContainerWrapper parent, - PrismContainerValue value, ValueStatus status, WrapperContext context) throws SchemaException { - context.setCreateIfEmpty(false); - return super.createValueWrapper(parent, value, status, context); - } - - -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/AbstractInputGuiComponentFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/AbstractInputGuiComponentFactory.java new file mode 100644 index 00000000000..e1ab8281721 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/AbstractInputGuiComponentFactory.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.panel; + +import java.util.List; + +import org.apache.wicket.AttributeModifier; +import org.apache.wicket.Component; +import org.apache.wicket.feedback.ComponentFeedbackMessageFilter; +import org.apache.wicket.markup.html.form.FormComponent; +import org.apache.wicket.markup.html.form.TextField; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.LambdaModel; +import org.springframework.beans.factory.annotation.Autowired; + +import com.evolveum.midpoint.gui.api.factory.GuiComponentFactory; +import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; +import com.evolveum.midpoint.web.component.prism.InputPanel; + +/** + * abstract factory for all InputPanel panels + * @param + */ +public abstract class AbstractInputGuiComponentFactory implements GuiComponentFactory> { + + @Autowired private GuiComponentRegistry componentRegistry; + + public GuiComponentRegistry getRegistry() { + return componentRegistry; + } + + @Override + public Panel createPanel(PrismPropertyPanelContext panelCtx) { + InputPanel panel = getPanel(panelCtx); + return panel; + } + + @Override + public void configure(PrismPropertyPanelContext panelCtx, Component component) { + if (!(component instanceof InputPanel)) { + return; + } + InputPanel panel = (InputPanel) component; + final List formComponents = panel.getFormComponents(); + for (FormComponent formComponent : formComponents) { + PrismPropertyWrapper propertyWrapper = panelCtx.unwrapWrapperModel(); + IModel label = LambdaModel.of(propertyWrapper::getDisplayName); + formComponent.setLabel(label); + formComponent.setRequired(panelCtx.isMandatory()); + + if (formComponent instanceof TextField) { + formComponent.add(new AttributeModifier("size", "42")); + } + formComponent.add(panelCtx.getAjaxEventBehavior()); + formComponent.add(panelCtx.getVisibleEnableBehavior()); + } + + panel.getValidatableComponent().add(panelCtx.getExpressionValidator()); + panelCtx.getFeedback().setFilter(new ComponentFeedbackMessageFilter(panel.getValidatableComponent())); + + } + + @Override + public Integer getOrder() { + return Integer.MAX_VALUE; + } + + protected abstract InputPanel getPanel(PrismPropertyPanelContext panelCtx); +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/AssociationAndExpressionPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/AssociationAndExpressionPanelFactory.java similarity index 89% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/AssociationAndExpressionPanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/AssociationAndExpressionPanelFactory.java index a8fb2c6caf6..1c9c9e5d487 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/AssociationAndExpressionPanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/AssociationAndExpressionPanelFactory.java @@ -1,55 +1,55 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import javax.annotation.PostConstruct; - -import org.apache.wicket.markup.html.panel.Panel; -import org.springframework.stereotype.Component; - -import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.impl.prism.ExpressionWrapper; -import com.evolveum.midpoint.web.component.input.AssociationExpressionValuePanel; -import com.evolveum.midpoint.web.component.input.SimpleValueExpressionPanel; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType; - -@Component -public class AssociationAndExpressionPanelFactory extends AbstractGuiComponentFactory { - - @PostConstruct - public void register() { - getRegistry().addToRegistry(this); - } - - @Override - protected Panel getPanel(PrismPropertyPanelContext panelCtx) { - ExpressionWrapper expressionWrapper = (ExpressionWrapper) panelCtx.unwrapWrapperModel(); - - if (expressionWrapper.isAttributeExpression()) { - return new SimpleValueExpressionPanel(panelCtx.getComponentId(), panelCtx.getRealValueModel()); - } - - return new AssociationExpressionValuePanel(panelCtx.getComponentId(), panelCtx.getRealValueModel(), expressionWrapper.getConstruction()); - - } - - @Override - public boolean match(IW wrapper) { - if (wrapper == null) { - return false; - } - - if (!(wrapper instanceof ExpressionWrapper)) { - return false; - } - ExpressionWrapper expressionWrapper = (ExpressionWrapper) wrapper; - return expressionWrapper.isAssociationExpression() || expressionWrapper.isAttributeExpression(); - } - - -} +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.panel; + +import javax.annotation.PostConstruct; + +import org.apache.wicket.markup.html.panel.Panel; +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.impl.prism.wrapper.ExpressionWrapper; +import com.evolveum.midpoint.web.component.input.AssociationExpressionValuePanel; +import com.evolveum.midpoint.web.component.input.SimpleValueExpressionPanel; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType; + +@Component +public class AssociationAndExpressionPanelFactory extends AbstractGuiComponentFactory { + + @PostConstruct + public void register() { + getRegistry().addToRegistry(this); + } + + @Override + protected Panel getPanel(PrismPropertyPanelContext panelCtx) { + ExpressionWrapper expressionWrapper = (ExpressionWrapper) panelCtx.unwrapWrapperModel(); + + if (expressionWrapper.isAttributeExpression()) { + return new SimpleValueExpressionPanel(panelCtx.getComponentId(), panelCtx.getRealValueModel()); + } + + return new AssociationExpressionValuePanel(panelCtx.getComponentId(), panelCtx.getRealValueModel(), expressionWrapper.getConstruction()); + + } + + @Override + public boolean match(IW wrapper) { + if (wrapper == null) { + return false; + } + + if (!(wrapper instanceof ExpressionWrapper)) { + return false; + } + ExpressionWrapper expressionWrapper = (ExpressionWrapper) wrapper; + return expressionWrapper.isAssociationExpression() || expressionWrapper.isAttributeExpression(); + } + + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ConditionPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ConditionPanelFactory.java similarity index 89% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ConditionPanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ConditionPanelFactory.java index 88bf224a156..f3d1fcb85b4 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ConditionPanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ConditionPanelFactory.java @@ -4,12 +4,10 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.web.page.admin.configuration.component.EmptyOnBlurAjaxFormUpdatingBehaviour; import com.evolveum.midpoint.web.page.admin.configuration.component.EmptyOnChangeAjaxFormUpdatingBehavior; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/DatePanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/DatePanelFactory.java similarity index 80% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/DatePanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/DatePanelFactory.java index 862761b0b8d..5463bad9643 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/DatePanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/DatePanelFactory.java @@ -4,22 +4,21 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import javax.annotation.PostConstruct; import javax.xml.datatype.XMLGregorianCalendar; +import com.evolveum.midpoint.web.component.prism.InputPanel; + import org.apache.wicket.extensions.yui.calendar.DateTimeField; import org.apache.wicket.markup.html.form.Form; -import org.apache.wicket.markup.html.panel.Panel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.web.component.input.DatePanel; @@ -31,7 +30,7 @@ * */ @Component -public class DatePanelFactory extends AbstractGuiComponentFactory { +public class DatePanelFactory extends AbstractInputGuiComponentFactory { private static final long serialVersionUID = 1L; @@ -47,7 +46,7 @@ public boolean match(IW wrapper) { } @Override - protected Panel getPanel(PrismPropertyPanelContext panelCtx) { + protected InputPanel getPanel(PrismPropertyPanelContext panelCtx) { DatePanel panel = new DatePanel(panelCtx.getComponentId(), panelCtx.getRealValueModel()); Form form = Form.findForm(panelCtx.getForm()); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/DropDownChoicePanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/DropDownChoicePanelFactory.java similarity index 54% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/DropDownChoicePanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/DropDownChoicePanelFactory.java index 8510a37ae75..6076ea382da 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/DropDownChoicePanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/DropDownChoicePanelFactory.java @@ -4,72 +4,57 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import java.util.List; import javax.annotation.PostConstruct; import javax.xml.namespace.QName; -import org.apache.wicket.markup.html.panel.Panel; -import org.apache.wicket.model.IModel; +import com.evolveum.midpoint.web.component.prism.InputPanel; + import org.apache.wicket.model.Model; -import org.apache.wicket.model.PropertyModel; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.evolveum.midpoint.gui.api.factory.GuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.impl.page.admin.configuration.component.ProfilingLevel; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.prism.PrismProperty; -import com.evolveum.midpoint.prism.PrismPropertyDefinition; -import com.evolveum.midpoint.prism.PrismPropertyValue; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.web.component.input.DropDownChoicePanel; import com.evolveum.midpoint.web.component.input.QNameObjectTypeChoiceRenderer; import com.evolveum.midpoint.web.page.admin.configuration.component.EmptyOnChangeAjaxFormUpdatingBehavior; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LoggingLevelType; /** * @author katkav * */ @Component -public class DropDownChoicePanelFactory implements GuiComponentFactory> { - - private static final long serialVersionUID = 1L; - @Autowired GuiComponentRegistry registry; +public class DropDownChoicePanelFactory extends AbstractInputGuiComponentFactory { @PostConstruct public void register() { - registry.addToRegistry(this); + getRegistry().addToRegistry(this); } + @Override public boolean match(IW wrapper) { return AssignmentType.F_FOCUS_TYPE.equals(wrapper.getItemName()) || DOMUtil.XSD_QNAME.equals(wrapper.getTypeName()); } - @Override - public Panel createPanel(PrismPropertyPanelContext panelCtx) { - List typesList = null; + @Override + protected InputPanel getPanel(PrismPropertyPanelContext panelCtx) { + List typesList = WebComponentUtil.createObjectTypeList(); if (AssignmentType.F_FOCUS_TYPE.equals(panelCtx.getDefinitionName())){ typesList = WebComponentUtil.createFocusTypeList(); - } else { - typesList = WebComponentUtil.createObjectTypeList(); } - DropDownChoicePanel typePanel = new DropDownChoicePanel(panelCtx.getComponentId(), (IModel) panelCtx.getRealValueModel(), + DropDownChoicePanel typePanel = new DropDownChoicePanel(panelCtx.getComponentId(), panelCtx.getRealValueModel(), Model.ofList(typesList), new QNameObjectTypeChoiceRenderer(), true); typePanel.getBaseFormComponent().add(new EmptyOnChangeAjaxFormUpdatingBehavior()); typePanel.setOutputMarkupId(true); return typePanel; } - @Override public Integer getOrder() { return 10000; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/EnumPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/EnumPanelFactory.java similarity index 68% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/EnumPanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/EnumPanelFactory.java index 665aafe983e..26ab406de72 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/EnumPanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/EnumPanelFactory.java @@ -4,38 +4,31 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import javax.annotation.PostConstruct; -import org.apache.wicket.markup.html.panel.Panel; -import org.apache.wicket.model.IModel; -import org.springframework.beans.factory.annotation.Autowired; +import com.evolveum.midpoint.web.component.prism.InputPanel; + import org.springframework.stereotype.Component; -import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; /** * @author katka * */ @Component -public class EnumPanelFactory> extends AbstractGuiComponentFactory { - - private static final long serialVersionUID = 1L; - - @Autowired GuiComponentRegistry registry; +public class EnumPanelFactory> extends AbstractInputGuiComponentFactory { @PostConstruct public void register() { - registry.addToRegistry(this); + getRegistry().addToRegistry(this); } - private boolean isEnum(ItemWrapper property) { + private boolean isEnum(ItemWrapper property) { if (!(property instanceof PrismPropertyWrapper)) { return false; @@ -60,7 +53,7 @@ public boolean match(IW wrapper) { } @Override - protected Panel getPanel(PrismPropertyPanelContext panelCtx) { + protected InputPanel getPanel(PrismPropertyPanelContext panelCtx) { Class clazz = panelCtx.getTypeClass(); if (clazz != null) { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ExecuteScriptModel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ExecuteScriptModel.java similarity index 89% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ExecuteScriptModel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ExecuteScriptModel.java index 7b15f07184e..75cbfdfa3de 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ExecuteScriptModel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ExecuteScriptModel.java @@ -5,7 +5,7 @@ * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import org.apache.commons.lang3.StringUtils; import org.apache.wicket.ThreadContext; @@ -40,10 +40,8 @@ public String getObject() { return locator.getPrismContext().xmlSerializer().serializeRealValue(value); } catch (Exception e) { - // TODO handle!!!! LoggingUtils.logUnexpectedException(LOGGER, "Cannot serialize script", e); ThreadContext.getSession().error("Cannot serialize script: " + e.getMessage()); -// getSession().error("Cannot serialize filter"); } return null; } @@ -58,10 +56,8 @@ public void setObject(String object) { ExecuteScriptType script = locator.getPrismContext().parserFor(object).parseRealValue(ExecuteScriptType.class); baseModel.setObject(script); } catch (Exception e) { - // TODO handle!!!! LoggingUtils.logUnexpectedException(LOGGER, "Cannot parse script", e); ThreadContext.getSession().error("Cannot parse script: " + e.getMessage()); -// getSession().error("Cannot parse filter"); } } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ExecuteScriptWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ExecuteScriptWrapperFactory.java similarity index 70% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ExecuteScriptWrapperFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ExecuteScriptWrapperFactory.java index f525a556bd2..7facf0738a9 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ExecuteScriptWrapperFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ExecuteScriptWrapperFactory.java @@ -5,12 +5,11 @@ * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; -import org.apache.wicket.markup.html.panel.Panel; +import com.evolveum.midpoint.web.component.prism.InputPanel; -import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.web.component.input.TextAreaPanel; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ExecuteScriptType; @@ -20,7 +19,7 @@ import javax.annotation.PostConstruct; @Component -public class ExecuteScriptWrapperFactory extends AbstractGuiComponentFactory { +public class ExecuteScriptWrapperFactory extends AbstractInputGuiComponentFactory { @PostConstruct public void register() { @@ -38,7 +37,7 @@ public Integer getOrder() { } @Override - protected Panel getPanel(PrismPropertyPanelContext panelCtx) { + protected InputPanel getPanel(PrismPropertyPanelContext panelCtx) { return new TextAreaPanel<>(panelCtx.getComponentId(), new ExecuteScriptModel(panelCtx.getRealValueModel(), panelCtx.getPageBase()), 20); } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ExpressionModel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ExpressionModel.java similarity index 98% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ExpressionModel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ExpressionModel.java index feb187dc796..a47e0da5256 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ExpressionModel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ExpressionModel.java @@ -4,7 +4,7 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import com.evolveum.midpoint.web.util.ExpressionUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ItemPanelContext.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ItemPanelContext.java similarity index 55% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ItemPanelContext.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ItemPanelContext.java index 7d4d61e5d91..d3f8970b545 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ItemPanelContext.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ItemPanelContext.java @@ -1,106 +1,160 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import java.io.Serializable; - -import org.apache.commons.lang.ClassUtils; -import org.apache.wicket.Component; -import org.apache.wicket.markup.html.form.Form; -import org.apache.wicket.model.IModel; - -import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismReferenceValue; -import com.evolveum.midpoint.prism.PrismValue; -import com.evolveum.midpoint.prism.path.ItemName; - -public abstract class ItemPanelContext implements Serializable { - - private String componentId; - - private Component parentComponent; - - private IModel itemWrapper; - private ItemRealValueModel realValueModel; - - private Form form; - - public ItemPanelContext(IModel itemWrapper) { - this.itemWrapper = itemWrapper; - } - - public IW unwrapWrapperModel() { - return itemWrapper.getObject(); - } - - public PageBase getPageBase() { - return (PageBase) parentComponent.getPage(); - } - - public String getComponentId() { - return componentId; - } - - public PrismContext getPrismContext() { - return unwrapWrapperModel().getPrismContext(); - } - - public ItemName getDefinitionName() { - return unwrapWrapperModel().getItemName(); - } - - public Component getParentComponent() { - return parentComponent; - } - - public Class getTypeClass() { - Class clazz = unwrapWrapperModel().getTypeClass(); - if (clazz == null) { - clazz = getPrismContext().getSchemaRegistry().determineClassForType(unwrapWrapperModel().getTypeName()); - } - if (clazz != null && clazz.isPrimitive()) { - clazz = ClassUtils.primitiveToWrapper(clazz); - } - return clazz; - } - - public ItemRealValueModel getRealValueModel() { - return realValueModel; - } - - public > void setRealValueModel(IModel valueWrapper) { - this.realValueModel = new ItemRealValueModel<>(valueWrapper); - } - - - public void setComponentId(String componentId) { - this.componentId = componentId; - } - - public void setParentComponent(Component parentComponent) { - this.parentComponent = parentComponent; - } - - -/** - * @return the form - */ -public Form getForm() { - return form; -} - -/** - * @param form the form to set - */ -public void setForm(Form form) { - this.form = form; -} - -} +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.panel; + +import java.io.Serializable; + +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemMandatoryHandler; + +import com.evolveum.midpoint.web.component.message.FeedbackAlerts; + +import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; + +import com.evolveum.midpoint.web.util.ExpressionValidator; + +import org.apache.commons.lang.ClassUtils; +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxEventBehavior; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.model.IModel; + +import com.evolveum.midpoint.gui.api.page.PageBase; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.path.ItemName; + +public abstract class ItemPanelContext implements Serializable { + + private String componentId; + + private Component parentComponent; + + private IModel itemWrapper; + private ItemRealValueModel realValueModel; + + private Form form; + private AjaxEventBehavior ajaxEventBehavior; + private ItemMandatoryHandler mandatoryHandler; + private VisibleEnableBehaviour visibleEnableBehaviour; + private ExpressionValidator expressionValidator; + private FeedbackAlerts feedback; + + public ItemPanelContext(IModel itemWrapper) { + this.itemWrapper = itemWrapper; + } + + public IW unwrapWrapperModel() { + return itemWrapper.getObject(); + } + + public PageBase getPageBase() { + return (PageBase) parentComponent.getPage(); + } + + public String getComponentId() { + return componentId; + } + + public PrismContext getPrismContext() { + return unwrapWrapperModel().getPrismContext(); + } + + public ItemName getDefinitionName() { + return unwrapWrapperModel().getItemName(); + } + + public Component getParentComponent() { + return parentComponent; + } + + public Class getTypeClass() { + Class clazz = unwrapWrapperModel().getTypeClass(); + if (clazz == null) { + clazz = getPrismContext().getSchemaRegistry().determineClassForType(unwrapWrapperModel().getTypeName()); + } + if (clazz != null && clazz.isPrimitive()) { + clazz = ClassUtils.primitiveToWrapper(clazz); + } + return clazz; + } + + public ItemRealValueModel getRealValueModel() { + return realValueModel; + } + + public > void setRealValueModel(IModel valueWrapper) { + this.realValueModel = new ItemRealValueModel<>(valueWrapper); + } + + + public void setComponentId(String componentId) { + this.componentId = componentId; + } + + public void setParentComponent(Component parentComponent) { + this.parentComponent = parentComponent; + } + + public void setAjaxEventBehavior(AjaxEventBehavior ajaxEventBehavior) { + this.ajaxEventBehavior = ajaxEventBehavior; + } + + public AjaxEventBehavior getAjaxEventBehavior() { + return ajaxEventBehavior; + } + + public void setMandatoryHandler(ItemMandatoryHandler mandatoryHandler) { + this.mandatoryHandler = mandatoryHandler; + } + + public void setVisibleEnableBehaviour(VisibleEnableBehaviour visibleEnableBehaviour) { + this.visibleEnableBehaviour = visibleEnableBehaviour; + } + + public VisibleEnableBehaviour getVisibleEnableBehavior() { + return visibleEnableBehaviour; + } + + public boolean isMandatory() { + if (mandatoryHandler != null) { + return mandatoryHandler.isMandatory(itemWrapper.getObject()); + } + return itemWrapper.getObject().isMandatory(); + } + + public void setExpressionValidator(ExpressionValidator expressionValidator) { + this.expressionValidator = expressionValidator; + } + + public ExpressionValidator getExpressionValidator() { + return expressionValidator; + } + + public void setFeedback(FeedbackAlerts feedback) { + this.feedback = feedback; + } + + public FeedbackAlerts getFeedback() { + return feedback; + } + + /** + * @return the form + */ +public Form getForm() { + return form; +} + +/** + * @param form the form to set + */ +public void setForm(Form form) { + this.form = form; +} + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ItemPathPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ItemPathPanelFactory.java similarity index 89% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ItemPathPanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ItemPathPanelFactory.java index 70fabff70d7..b4eb273b954 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ItemPathPanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ItemPathPanelFactory.java @@ -4,12 +4,11 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import java.io.Serializable; import javax.annotation.PostConstruct; -import javax.annotation.Priority; import org.apache.wicket.markup.html.panel.Panel; import org.springframework.beans.factory.annotation.Autowired; @@ -18,9 +17,8 @@ import com.evolveum.midpoint.gui.api.component.path.ItemPathDto; import com.evolveum.midpoint.gui.api.component.path.ItemPathPanel; import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; import com.evolveum.prism.xml.ns._public.types_3.ItemPathType; /** diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ItemRealValueModel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ItemRealValueModel.java similarity index 81% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ItemRealValueModel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ItemRealValueModel.java index a76048362ef..148313f090f 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ItemRealValueModel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ItemRealValueModel.java @@ -5,12 +5,12 @@ * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.PropertyModel; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; public class ItemRealValueModel extends PropertyModel{ diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/LinkedReferencePanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/LinkedReferencePanelFactory.java similarity index 80% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/LinkedReferencePanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/LinkedReferencePanelFactory.java index 0aed11becff..70570200e70 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/LinkedReferencePanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/LinkedReferencePanelFactory.java @@ -4,15 +4,13 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import com.evolveum.midpoint.gui.api.factory.GuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismReferencePanel; -import com.evolveum.midpoint.gui.impl.prism.PrismReferenceValueWrapperImpl; -import com.evolveum.midpoint.gui.impl.prism.PrismReferenceWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismReferenceWrapperImpl; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismReferenceValueWrapperImpl; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismReferenceWrapperImpl; import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; @@ -32,11 +30,9 @@ @Component public class LinkedReferencePanelFactory implements GuiComponentFactory> { - private static final long serialVersionUID = 1L; private static final Trace LOGGER = TraceManager.getTrace(LinkedReferencePanelFactory.class); - @Autowired - GuiComponentRegistry registry; + @Autowired private GuiComponentRegistry registry; @PostConstruct public void register() { @@ -55,7 +51,7 @@ public boolean match(IW wrapper) { if (match){ try { PrismReferenceValueWrapperImpl valueWrapper = (PrismReferenceValueWrapperImpl) - ((PrismReferenceWrapperImpl) wrapper).getValue(); + wrapper.getValue(); valueWrapper.setLink(true); } catch (SchemaException e){ LOGGER.warn("Unable to set isLink status for PrismReferenceValueWrapper: {}", e.getLocalizedMessage()); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/LockoutStatusPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/LockoutStatusPanelFactory.java similarity index 76% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/LockoutStatusPanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/LockoutStatusPanelFactory.java index 75a65848144..602ff9cef65 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/LockoutStatusPanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/LockoutStatusPanelFactory.java @@ -5,22 +5,17 @@ * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import javax.annotation.PostConstruct; -import org.apache.wicket.feedback.ComponentFeedbackMessageFilter; import org.apache.wicket.markup.html.panel.Panel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.evolveum.midpoint.gui.api.factory.GuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.prism.PrismProperty; -import com.evolveum.midpoint.prism.PrismPropertyDefinition; -import com.evolveum.midpoint.prism.PrismPropertyValue; import com.evolveum.midpoint.web.component.LockoutStatusPanel; import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.LockoutStatusType; @@ -28,8 +23,6 @@ @Component public class LockoutStatusPanelFactory implements GuiComponentFactory> { - private static final long serialVersionUID = 1L; - @Autowired GuiComponentRegistry registry; @PostConstruct diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ModificationsPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ModificationsPanelFactory.java similarity index 87% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ModificationsPanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ModificationsPanelFactory.java index c223d0a0040..d8cec710d23 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ModificationsPanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ModificationsPanelFactory.java @@ -4,7 +4,7 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import javax.annotation.PostConstruct; @@ -13,9 +13,8 @@ import org.springframework.stereotype.Component; import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.schema.DeltaConvertor; @@ -31,13 +30,9 @@ @Component public class ModificationsPanelFactory extends AbstractGuiComponentFactory { - private static final long serialVersionUID = 1L; - - @Autowired private GuiComponentRegistry registry; - @PostConstruct public void register() { - registry.addToRegistry(this); + getRegistry().addToRegistry(this); } @Override diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ObjectDeltaModel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ObjectDeltaModel.java similarity index 94% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ObjectDeltaModel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ObjectDeltaModel.java index 85bc5f59646..e64fcc5ea02 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ObjectDeltaModel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ObjectDeltaModel.java @@ -5,7 +5,7 @@ * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; @@ -17,7 +17,6 @@ import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ExecuteScriptType; public class ObjectDeltaModel implements IModel { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ObjectDeltaPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ObjectDeltaPanelFactory.java similarity index 71% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ObjectDeltaPanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ObjectDeltaPanelFactory.java index 8139d3e779c..888017c2ff8 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ObjectDeltaPanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ObjectDeltaPanelFactory.java @@ -5,22 +5,22 @@ * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import javax.annotation.PostConstruct; import com.evolveum.midpoint.web.component.input.TextAreaPanel; -import org.apache.wicket.markup.html.panel.Panel; +import com.evolveum.midpoint.web.component.prism.InputPanel; + import org.springframework.stereotype.Component; -import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; @Component -public class ObjectDeltaPanelFactory extends AbstractGuiComponentFactory { +public class ObjectDeltaPanelFactory extends AbstractInputGuiComponentFactory { @PostConstruct public void register() { @@ -33,7 +33,7 @@ public Integer getOrder() { } @Override - protected Panel getPanel(PrismPropertyPanelContext panelCtx) { + protected InputPanel getPanel(PrismPropertyPanelContext panelCtx) { return new TextAreaPanel<>(panelCtx.getComponentId(), new ObjectDeltaModel(panelCtx.getRealValueModel(), panelCtx.getPageBase()), 20); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/PolyStringEditorPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/PolyStringEditorPanelFactory.java new file mode 100644 index 00000000000..05c8d55fe6f --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/PolyStringEditorPanelFactory.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.panel; + +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.gui.impl.prism.panel.PolyStringEditorPanel; +import com.evolveum.midpoint.web.component.prism.InputPanel; +import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; + +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +/** + * Created by honchar + */ +@Component +public class PolyStringEditorPanelFactory extends AbstractInputGuiComponentFactory { + + @PostConstruct + public void register() { + getRegistry().addToRegistry(this); + } + + @Override + public boolean match(IW wrapper) { + return PolyStringType.COMPLEX_TYPE.equals(wrapper.getTypeName()); + } + + @Override + protected InputPanel getPanel(PrismPropertyPanelContext panelCtx) { + return new PolyStringEditorPanel(panelCtx.getComponentId(), panelCtx.getRealValueModel(), + panelCtx.getPredefinedValues(), panelCtx.hasValueEnumerationRef()); + } + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismContainerPanelContext.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/PrismContainerPanelContext.java similarity index 77% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismContainerPanelContext.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/PrismContainerPanelContext.java index e28a82c2206..8d065bf2b18 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismContainerPanelContext.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/PrismContainerPanelContext.java @@ -1,40 +1,40 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; -import com.evolveum.midpoint.prism.*; -import org.apache.wicket.model.IModel; - -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; - -/** - * @author katka - * - */ -public class PrismContainerPanelContext extends ItemPanelContext>{ - - private IModel> valueWrapperModel; - - public PrismContainerPanelContext(IModel> itemWrapper) { - super(itemWrapper); - // TODO Auto-generated constructor stub - } - - @Override - public > void setRealValueModel(IModel valueWrapper) { - super.setRealValueModel(valueWrapper); - this.valueWrapperModel = (IModel>) valueWrapper; - } - - public IModel> getValueWrapper() { - return valueWrapperModel; - } - - -} +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.panel; + +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; +import com.evolveum.midpoint.prism.*; +import org.apache.wicket.model.IModel; + +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; + +/** + * @author katka + * + */ +public class PrismContainerPanelContext extends ItemPanelContext>{ + + private IModel> valueWrapperModel; + + public PrismContainerPanelContext(IModel> itemWrapper) { + super(itemWrapper); + // TODO Auto-generated constructor stub + } + + @Override + public > void setRealValueModel(IModel valueWrapper) { + super.setRealValueModel(valueWrapper); + this.valueWrapperModel = (IModel>) valueWrapper; + } + + public IModel> getValueWrapper() { + return valueWrapperModel; + } + + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismPropertyPanelContext.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/PrismPropertyPanelContext.java similarity index 76% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismPropertyPanelContext.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/PrismPropertyPanelContext.java index f9e7884dc07..24f9f55c3f2 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismPropertyPanelContext.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/PrismPropertyPanelContext.java @@ -1,33 +1,31 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.prism.PrismContainer; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; -import org.apache.wicket.model.IModel; - -/** - * @author katka - * - */ -public class PrismPropertyPanelContext extends ItemPanelContext>{ - - - public PrismPropertyPanelContext(IModel> itemWrapper) { - super(itemWrapper); - } - - public LookupTableType getPredefinedValues() { - return unwrapWrapperModel().getPredefinedValues(); - } - - public boolean hasValueEnumerationRef() { - return unwrapWrapperModel().getValueEnumerationRef() != null; - } -} +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.panel; + +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; +import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; +import org.apache.wicket.model.IModel; + +/** + * @author katka + * + */ +public class PrismPropertyPanelContext extends ItemPanelContext>{ + + + public PrismPropertyPanelContext(IModel> itemWrapper) { + super(itemWrapper); + } + + public LookupTableType getPredefinedValues() { + return unwrapWrapperModel().getPredefinedValues(); + } + + public boolean hasValueEnumerationRef() { + return unwrapWrapperModel().getValueEnumerationRef() != null; + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismReferencePanelContext.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/PrismReferencePanelContext.java similarity index 76% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismReferencePanelContext.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/PrismReferencePanelContext.java index 9832eb14589..40143e788d0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismReferencePanelContext.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/PrismReferencePanelContext.java @@ -1,34 +1,30 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.factory; - -import java.util.List; - -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.prism.*; - -import org.apache.wicket.model.IModel; - -import com.evolveum.midpoint.gui.impl.prism.PrismReferenceWrapper; -import com.evolveum.midpoint.prism.query.ObjectFilter; - -/** - * @author katka - * - */ -public class PrismReferencePanelContext extends ItemPanelContext>{ - - public PrismReferencePanelContext(IModel> itemWrapper) { - super(itemWrapper); - } - - public ObjectFilter getFilter() { - return unwrapWrapperModel().getFilter(); - } - -} +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.panel; + +import com.evolveum.midpoint.prism.*; + +import org.apache.wicket.model.IModel; + +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismReferenceWrapper; +import com.evolveum.midpoint.prism.query.ObjectFilter; + +/** + * @author katka + * + */ +public class PrismReferencePanelContext extends ItemPanelContext>{ + + public PrismReferencePanelContext(IModel> itemWrapper) { + super(itemWrapper); + } + + public ObjectFilter getFilter() { + return unwrapWrapperModel().getFilter(); + } + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ProfilingLoggerLevelPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ProfilingLoggerLevelPanelFactory.java similarity index 63% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ProfilingLoggerLevelPanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ProfilingLoggerLevelPanelFactory.java index 7a675e8f2fb..7b1067a181a 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ProfilingLoggerLevelPanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ProfilingLoggerLevelPanelFactory.java @@ -4,42 +4,30 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; - -import java.io.Serializable; +package com.evolveum.midpoint.gui.impl.factory.panel; import javax.annotation.PostConstruct; +import com.evolveum.midpoint.web.component.prism.InputPanel; + import org.apache.wicket.markup.html.form.EnumChoiceRenderer; -import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.Model; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.evolveum.midpoint.gui.api.factory.GuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.impl.page.admin.configuration.component.ProfilingLevel; -import com.evolveum.midpoint.gui.impl.prism.ProfilingClassLoggerContainerValueWrapperImpl; -import com.evolveum.midpoint.gui.impl.prism.ProfilingClassLoggerContainerWrapperImpl; -import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.gui.impl.prism.wrapper.ProfilingClassLoggerContainerValueWrapperImpl; import com.evolveum.midpoint.web.component.input.DropDownChoicePanel; import com.evolveum.midpoint.xml.ns._public.common.common_3.ClassLoggerConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LoggingConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.LoggingLevelType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; /** * @author skublik * */ @Component -public class ProfilingLoggerLevelPanelFactory implements GuiComponentFactory>, Serializable { - - private static final long serialVersionUID = 1L; - - @Autowired private transient GuiComponentRegistry registry; +public class ProfilingLoggerLevelPanelFactory extends AbstractInputGuiComponentFactory { @Override public Integer getOrder() { @@ -48,7 +36,7 @@ public Integer getOrder() { @PostConstruct public void register() { - registry.addToRegistry(this); + getRegistry().addToRegistry(this); } @Override @@ -56,8 +44,9 @@ public boolean match(IW wrapper) { return wrapper.getParent() instanceof ProfilingClassLoggerContainerValueWrapperImpl && wrapper.getItemName().equals(ClassLoggerConfigurationType.F_LEVEL); } + //FIXME model @Override - public Panel createPanel(PrismPropertyPanelContext panelCtx) { + protected InputPanel getPanel(PrismPropertyPanelContext panelCtx) { DropDownChoicePanel dropDownProfilingLevel = new DropDownChoicePanel<>(panelCtx.getComponentId(), new Model() { private static final long serialVersionUID = 1L; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/QueryTextAreaPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/QueryTextAreaPanelFactory.java similarity index 55% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/QueryTextAreaPanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/QueryTextAreaPanelFactory.java index 09072ce11cf..7f4d130cfbe 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/QueryTextAreaPanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/QueryTextAreaPanelFactory.java @@ -5,43 +5,37 @@ * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; -import java.io.Serializable; import javax.annotation.PostConstruct; import com.evolveum.midpoint.web.component.input.QueryTextAreaPanel; -import org.apache.wicket.markup.html.panel.Panel; -import org.springframework.beans.factory.annotation.Autowired; +import com.evolveum.midpoint.web.component.prism.InputPanel; + import org.springframework.stereotype.Component; -import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.web.component.input.TextAreaPanel; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; import com.evolveum.prism.xml.ns._public.query_3.QueryType; @Component -public class QueryTextAreaPanelFactory extends AbstractGuiComponentFactory { - - private static final long serialVersionUID = 1L; - - @Autowired private GuiComponentRegistry registry; +public class QueryTextAreaPanelFactory extends AbstractInputGuiComponentFactory { @PostConstruct public void register() { - registry.addToRegistry(this); + getRegistry().addToRegistry(this); } @Override public boolean match(IW wrapper) { - return QueryType.COMPLEX_TYPE.equals(wrapper.getTypeName()); // || CleanupPoliciesType.COMPLEX_TYPE.equals(wrapper.getTypeName()); + return QueryType.COMPLEX_TYPE.equals(wrapper.getTypeName()); } + //FIXME shoud be textAreapanel with custom model + //TODO cleanup @Override - protected Panel getPanel(PrismPropertyPanelContext panelCtx) { + protected InputPanel getPanel(PrismPropertyPanelContext panelCtx) { int size = 10; if (FocusType.F_DESCRIPTION.equals(panelCtx.getDefinitionName())) { size = 2; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/RelationPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/RelationPanelFactory.java similarity index 81% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/RelationPanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/RelationPanelFactory.java index e112466876d..0fbcb95f9e8 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/RelationPanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/RelationPanelFactory.java @@ -4,16 +4,16 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import javax.annotation.PostConstruct; import javax.xml.namespace.QName; -import org.apache.wicket.markup.html.panel.Panel; +import com.evolveum.midpoint.web.component.prism.InputPanel; + import org.springframework.stereotype.Component; -import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.impl.model.RelationModel; import com.evolveum.midpoint.gui.impl.validator.RelationValidator; import com.evolveum.midpoint.prism.path.ItemPath; @@ -24,7 +24,7 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; @Component -public class RelationPanelFactory extends AbstractGuiComponentFactory { +public class RelationPanelFactory extends AbstractInputGuiComponentFactory { @PostConstruct public void register() { @@ -32,7 +32,7 @@ public void register() { } @Override - protected Panel getPanel(PrismPropertyPanelContext panelCtx) { + protected InputPanel getPanel(PrismPropertyPanelContext panelCtx) { TextPanel relationPanel = new TextPanel<>(panelCtx.getComponentId(), new RelationModel(panelCtx.getRealValueModel())); relationPanel.getBaseFormComponent().add(new RelationValidator()); return relationPanel; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ResourceAttributeRefPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ResourceAttributeRefPanelFactory.java similarity index 80% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ResourceAttributeRefPanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ResourceAttributeRefPanelFactory.java index 1c7fcb10209..a3ef9e9d202 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ResourceAttributeRefPanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ResourceAttributeRefPanelFactory.java @@ -5,50 +5,38 @@ * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import com.evolveum.midpoint.common.refinery.RefinedAssociationDefinition; import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; import com.evolveum.midpoint.gui.api.component.autocomplete.AutoCompleteQNamePanel; -import com.evolveum.midpoint.gui.api.component.autocomplete.AutoCompleteTextPanel; -import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.prism.ConstructionValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.impl.prism.wrapper.ConstructionValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; import com.evolveum.midpoint.prism.path.ItemName; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition; import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; -import com.evolveum.midpoint.schema.processor.ResourceSchema; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.page.admin.configuration.component.EmptyOnChangeAjaxFormUpdatingBehavior; +import com.evolveum.midpoint.web.component.prism.InputPanel; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import com.evolveum.prism.xml.ns._public.types_3.ItemPathType; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.markup.html.panel.Panel; + import org.apache.wicket.model.IModel; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; -import javax.xml.namespace.QName; import java.io.Serializable; import java.util.*; import java.util.stream.Collectors; +//FIXME serializable? @Component -public class ResourceAttributeRefPanelFactory extends AbstractGuiComponentFactory implements Serializable { +public class ResourceAttributeRefPanelFactory extends AbstractInputGuiComponentFactory implements Serializable { private static final transient Trace LOGGER = TraceManager.getTrace(ResourceAttributeRefPanelFactory.class); @@ -58,7 +46,7 @@ public void register() { } @Override - protected Panel getPanel(PrismPropertyPanelContext panelCtx) { + protected InputPanel getPanel(PrismPropertyPanelContext panelCtx) { AutoCompleteQNamePanel autoCompleteTextPanel = new AutoCompleteQNamePanel(panelCtx.getComponentId(), new AttributeRefModel(panelCtx.getRealValueModel())) { @@ -69,8 +57,6 @@ public Collection loadChoices() { }; - autoCompleteTextPanel.getBaseFormComponent().add(new EmptyOnChangeAjaxFormUpdatingBehavior()); - return autoCompleteTextPanel; } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/SearchFilterPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/SearchFilterPanelFactory.java similarity index 64% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/SearchFilterPanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/SearchFilterPanelFactory.java index b3b665a82d3..1d543adc758 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/SearchFilterPanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/SearchFilterPanelFactory.java @@ -5,40 +5,26 @@ * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import javax.annotation.PostConstruct; -import org.apache.commons.lang3.StringUtils; import org.apache.wicket.markup.html.panel.Panel; -import org.apache.wicket.model.IModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.LoggingUtils; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.page.admin.reports.component.AceEditorPanel; import com.evolveum.prism.xml.ns._public.query_3.SearchFilterType; -import java.io.Serializable; - @Component public class SearchFilterPanelFactory extends AbstractGuiComponentFactory { - private static final long serialVersionUID = 1L; - - @Autowired private transient GuiComponentRegistry registry; - @PostConstruct public void register() { - registry.addToRegistry(this); + getRegistry().addToRegistry(this); } @Override diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/SearchFilterTypeModel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/SearchFilterTypeModel.java similarity index 97% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/SearchFilterTypeModel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/SearchFilterTypeModel.java index 93de94287fe..2a3cb5a64f9 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/SearchFilterTypeModel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/SearchFilterTypeModel.java @@ -4,7 +4,7 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import com.evolveum.midpoint.gui.api.page.PageBase; import com.evolveum.midpoint.util.exception.SchemaException; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TaskIntentFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/TaskIntentFactory.java similarity index 84% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TaskIntentFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/TaskIntentFactory.java index 1b3ed728454..98017b067ee 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TaskIntentFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/TaskIntentFactory.java @@ -1,79 +1,80 @@ -/* - * Copyright (c) 2010-2017 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.gui.impl.factory; - -import java.io.Serializable; -import java.util.Collections; -import java.util.Iterator; -import javax.annotation.PostConstruct; - -import org.apache.wicket.extensions.ajax.markup.html.autocomplete.StringAutoCompleteRenderer; -import org.apache.wicket.markup.html.panel.Panel; - -import com.evolveum.midpoint.gui.api.component.autocomplete.AutoCompleteTextPanel; -import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.api.util.WebPrismUtil; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismPropertyValue; -import com.evolveum.midpoint.prism.PrismReferenceValue; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.task.api.Task; -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.TaskType; - -import org.springframework.stereotype.Component; - -@Component -public class TaskIntentFactory extends AbstractGuiComponentFactory implements Serializable { - - @PostConstruct - public void register() { - getRegistry().addToRegistry(this); - } - - @Override - protected Panel getPanel(PrismPropertyPanelContext panelCtx) { - return new AutoCompleteTextPanel(panelCtx.getComponentId(), panelCtx.getRealValueModel(), String.class, StringAutoCompleteRenderer.INSTANCE) { - - @Override - public Iterator getIterator(String input) { - PrismPropertyWrapper itemWrapper = panelCtx.unwrapWrapperModel(); - PrismReferenceValue objectRef = WebPrismUtil.findSingleReferenceValue(itemWrapper, ItemPath.create(TaskType.F_OBJECT_REF)); - - Task task = panelCtx.getPageBase().createSimpleTask("load resource"); - PrismObject resourceType = WebModelServiceUtils.loadObject(objectRef, ResourceType.COMPLEX_TYPE, panelCtx.getPageBase(), task, task.getResult()); - - if (resourceType == null) { - return Collections.emptyIterator(); - } - - PrismPropertyValue kindPropValue = WebPrismUtil.findSinglePropertyValue(itemWrapper, ItemPath.create(TaskType.F_EXTENSION, SchemaConstants.MODEL_EXTENSION_KIND)); - if (kindPropValue == null) { - return Collections.emptyIterator(); - } - return WebComponentUtil.getIntensForKind(resourceType, kindPropValue.getRealValue(), panelCtx.getPageBase()).iterator(); - } - }; - } - - @Override - public boolean match(IW wrapper) { - return wrapper.getPath().equivalent(ItemPath.create(TaskType.F_EXTENSION, SchemaConstants.MODEL_EXTENSION_INTENT)); - } - - @Override - public Integer getOrder() { - return 100; - } -} +/* + * Copyright (c) 2010-2017 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.gui.impl.factory.panel; + +import java.io.Serializable; +import java.util.Collections; +import java.util.Iterator; +import javax.annotation.PostConstruct; + +import com.evolveum.midpoint.web.component.prism.InputPanel; + +import org.apache.wicket.extensions.ajax.markup.html.autocomplete.StringAutoCompleteRenderer; + +import com.evolveum.midpoint.gui.api.component.autocomplete.AutoCompleteTextPanel; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; +import com.evolveum.midpoint.gui.api.util.WebPrismUtil; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismPropertyValue; +import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.task.api.Task; +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.TaskType; + +import org.springframework.stereotype.Component; + +//FIXME serializable? +@Component +public class TaskIntentFactory extends AbstractInputGuiComponentFactory implements Serializable { + + @PostConstruct + public void register() { + getRegistry().addToRegistry(this); + } + + @Override + protected InputPanel getPanel(PrismPropertyPanelContext panelCtx) { + return new AutoCompleteTextPanel(panelCtx.getComponentId(), panelCtx.getRealValueModel(), String.class, StringAutoCompleteRenderer.INSTANCE) { + + @Override + public Iterator getIterator(String input) { + PrismPropertyWrapper itemWrapper = panelCtx.unwrapWrapperModel(); + PrismReferenceValue objectRef = WebPrismUtil.findSingleReferenceValue(itemWrapper, ItemPath.create(TaskType.F_OBJECT_REF)); + + Task task = panelCtx.getPageBase().createSimpleTask("load resource"); + PrismObject resourceType = WebModelServiceUtils.loadObject(objectRef, ResourceType.COMPLEX_TYPE, panelCtx.getPageBase(), task, task.getResult()); + + if (resourceType == null) { + return Collections.emptyIterator(); + } + + PrismPropertyValue kindPropValue = WebPrismUtil.findSinglePropertyValue(itemWrapper, ItemPath.create(TaskType.F_EXTENSION, SchemaConstants.MODEL_EXTENSION_KIND)); + if (kindPropValue == null) { + return Collections.emptyIterator(); + } + return WebComponentUtil.getIntensForKind(resourceType, kindPropValue.getRealValue(), panelCtx.getPageBase()).iterator(); + } + }; + } + + @Override + public boolean match(IW wrapper) { + return wrapper.getPath().equivalent(ItemPath.create(TaskType.F_EXTENSION, SchemaConstants.MODEL_EXTENSION_INTENT)); + } + + @Override + public Integer getOrder() { + return 100; + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TaskObjectClassFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/TaskObjectClassFactory.java similarity index 70% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TaskObjectClassFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/TaskObjectClassFactory.java index 89dd8d86aef..4e2d266854c 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TaskObjectClassFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/TaskObjectClassFactory.java @@ -1,88 +1,80 @@ -/* - * Copyright (c) 2010-2017 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.gui.impl.factory; - -import java.io.Serializable; -import java.util.Collection; -import java.util.Collections; -import javax.annotation.PostConstruct; -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.gui.api.util.WebPrismUtil; - -import org.apache.wicket.markup.html.panel.Panel; -import org.springframework.stereotype.Component; - -import com.evolveum.midpoint.gui.api.component.autocomplete.AutoCompleteQNamePanel; -import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismReferenceWrapper; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismReferenceValue; -import com.evolveum.midpoint.prism.Referencable; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.schema.GetOperationOptions; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -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.logging.LoggingUtils; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; - -@Component -public class TaskObjectClassFactory extends AbstractGuiComponentFactory implements Serializable { - - - @PostConstruct - public void register() { - getRegistry().addToRegistry(this); - } - - @Override - protected Panel getPanel(PrismPropertyPanelContext panelCtx) { - return new AutoCompleteQNamePanel(panelCtx.getComponentId(), panelCtx.getRealValueModel()) { - - @Override - public Collection loadChoices() { - - PrismPropertyWrapper itemWrapper = panelCtx.unwrapWrapperModel(); - PrismReferenceValue objectRef = WebPrismUtil.findSingleReferenceValue(itemWrapper, ItemPath.create(TaskType.F_OBJECT_REF)); - Task task = panelCtx.getPageBase().createSimpleTask("load resource"); - PrismObject resourceType = WebModelServiceUtils.loadObject(objectRef, ResourceType.COMPLEX_TYPE, panelCtx.getPageBase(), task, task.getResult()); - - if (resourceType == null) { - return Collections.EMPTY_LIST; - } - return WebComponentUtil.loadResourceObjectClassValues(resourceType.asObjectable(), panelCtx.getPageBase()); - } - - @Override - protected boolean alwaysReload() { - return true; - } - }; - - } - - @Override - public boolean match(IW wrapper) { - return wrapper.getPath().equivalent(ItemPath.create(TaskType.F_EXTENSION, SchemaConstants.MODEL_EXTENSION_OBJECTCLASS)); - } - - @Override - public Integer getOrder() { - return 10000 - 10; - } -} +/* + * Copyright (c) 2010-2017 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.gui.impl.factory.panel; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import javax.annotation.PostConstruct; +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.gui.api.util.WebPrismUtil; + +import com.evolveum.midpoint.web.component.prism.InputPanel; + +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.gui.api.component.autocomplete.AutoCompleteQNamePanel; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; + +//FIXME serializable +@Component +public class TaskObjectClassFactory extends AbstractInputGuiComponentFactory implements Serializable { + + + @PostConstruct + public void register() { + getRegistry().addToRegistry(this); + } + + @Override + protected InputPanel getPanel(PrismPropertyPanelContext panelCtx) { + return new AutoCompleteQNamePanel(panelCtx.getComponentId(), panelCtx.getRealValueModel()) { + + @Override + public Collection loadChoices() { + + PrismPropertyWrapper itemWrapper = panelCtx.unwrapWrapperModel(); + PrismReferenceValue objectRef = WebPrismUtil.findSingleReferenceValue(itemWrapper, ItemPath.create(TaskType.F_OBJECT_REF)); + Task task = panelCtx.getPageBase().createSimpleTask("load resource"); + PrismObject resourceType = WebModelServiceUtils.loadObject(objectRef, ResourceType.COMPLEX_TYPE, panelCtx.getPageBase(), task, task.getResult()); + + if (resourceType == null) { + return Collections.EMPTY_LIST; + } + return WebComponentUtil.loadResourceObjectClassValues(resourceType.asObjectable(), panelCtx.getPageBase()); + } + + @Override + protected boolean alwaysReload() { + return true; + } + }; + + } + + @Override + public boolean match(IW wrapper) { + return wrapper.getPath().equivalent(ItemPath.create(TaskType.F_EXTENSION, SchemaConstants.MODEL_EXTENSION_OBJECTCLASS)); + } + + @Override + public Integer getOrder() { + return 10000 - 10; + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TextAreaPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/TextAreaPanelFactory.java similarity index 52% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TextAreaPanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/TextAreaPanelFactory.java index 809e08ec797..6569d17a0d0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TextAreaPanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/TextAreaPanelFactory.java @@ -5,44 +5,36 @@ * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import java.io.Serializable; import javax.annotation.PostConstruct; -import org.apache.wicket.markup.html.panel.Panel; -import org.springframework.beans.factory.annotation.Autowired; +import com.evolveum.midpoint.web.component.prism.InputPanel; + import org.springframework.stereotype.Component; -import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.web.component.input.TextAreaPanel; -import com.evolveum.midpoint.xml.ns._public.common.common_3.CleanupPoliciesType; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; -import com.evolveum.prism.xml.ns._public.query_3.QueryType; @Component -public class TextAreaPanelFactory extends AbstractGuiComponentFactory { - - private static final long serialVersionUID = 1L; +public class TextAreaPanelFactory extends AbstractInputGuiComponentFactory { - @Autowired private GuiComponentRegistry registry; @PostConstruct public void register() { - registry.addToRegistry(this); + getRegistry().addToRegistry(this); } @Override public boolean match(IW wrapper) { - return FocusType.F_DESCRIPTION.equals(wrapper.getItemName()); // || QueryType.COMPLEX_TYPE.equals(wrapper.getTypeName()); // || CleanupPoliciesType.COMPLEX_TYPE.equals(wrapper.getTypeName()); + return FocusType.F_DESCRIPTION.equals(wrapper.getItemName()); } @Override - protected Panel getPanel(PrismPropertyPanelContext panelCtx) { + protected InputPanel getPanel(PrismPropertyPanelContext panelCtx) { int size = 10; if (FocusType.F_DESCRIPTION.equals(panelCtx.getDefinitionName())) { size = 2; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TextPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/TextPanelFactory.java similarity index 68% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TextPanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/TextPanelFactory.java index c1cc7b11938..01310f7708f 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/TextPanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/TextPanelFactory.java @@ -1,68 +1,69 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.gui.impl.factory; - -import java.io.Serializable; -import java.util.Iterator; - -import javax.annotation.PostConstruct; -import javax.xml.namespace.QName; - -import org.apache.wicket.markup.html.panel.Panel; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.evolveum.midpoint.gui.api.component.autocomplete.AutoCompleteTextPanel; -import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.util.DOMUtil; -import com.evolveum.midpoint.web.component.input.TextPanel; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; - -@Component -public class TextPanelFactory extends AbstractGuiComponentFactory implements Serializable { - - private static final long serialVersionUID = 1L; - - @Autowired transient GuiComponentRegistry registry; - - @PostConstruct - public void register() { - registry.addToRegistry(this); - } - @Override - public boolean match(IW wrapper) { - QName type = wrapper.getTypeName(); - return DOMUtil.XSD_STRING.equals(type) || DOMUtil.XSD_DURATION.equals(type) || DOMUtil.XSD_LONG.equals(type) - || DOMUtil.XSD_ANYURI.equals(type) || DOMUtil.XSD_INT.equals(type) || DOMUtil.XSD_INTEGER.equals(type); - } - - @Override - protected Panel getPanel(PrismPropertyPanelContext panelCtx) { - LookupTableType lookupTable = panelCtx.getPredefinedValues(); - if (lookupTable == null) { - return new TextPanel<>(panelCtx.getComponentId(), - panelCtx.getRealValueModel(), panelCtx.getTypeClass(), false); - } - - return new AutoCompleteTextPanel(panelCtx.getComponentId(), - panelCtx.getRealValueModel(), panelCtx.getTypeClass(), panelCtx.hasValueEnumerationRef(), lookupTable) { - - private static final long serialVersionUID = 1L; - - @Override - public Iterator getIterator(String input) { - return (Iterator) prepareAutoCompleteList(input, lookupTable, panelCtx.getPageBase().getLocalizationService()).iterator(); - } - }; - } - -} +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.gui.impl.factory.panel; + +import java.io.Serializable; +import java.util.Iterator; +import java.util.List; + +import javax.annotation.PostConstruct; +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.common.LocalizationService; +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; + +import com.evolveum.midpoint.web.component.prism.InputPanel; + +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.gui.api.component.autocomplete.AutoCompleteTextPanel; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.util.DOMUtil; +import com.evolveum.midpoint.web.component.input.TextPanel; +import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; + +//FIXME serializable +@Component +public class TextPanelFactory extends AbstractInputGuiComponentFactory implements Serializable { + + @PostConstruct + public void register() { + getRegistry().addToRegistry(this); + } + + @Override + public boolean match(IW wrapper) { + QName type = wrapper.getTypeName(); + return DOMUtil.XSD_STRING.equals(type) || DOMUtil.XSD_DURATION.equals(type) || DOMUtil.XSD_LONG.equals(type) + || DOMUtil.XSD_ANYURI.equals(type) || DOMUtil.XSD_INT.equals(type) || DOMUtil.XSD_INTEGER.equals(type); + } + + @Override + protected InputPanel getPanel(PrismPropertyPanelContext panelCtx) { + LookupTableType lookupTable = panelCtx.getPredefinedValues(); + if (lookupTable == null) { + return new TextPanel<>(panelCtx.getComponentId(), + panelCtx.getRealValueModel(), panelCtx.getTypeClass(), false); + } + + return new AutoCompleteTextPanel(panelCtx.getComponentId(), + panelCtx.getRealValueModel(), panelCtx.getTypeClass(), panelCtx.hasValueEnumerationRef(), lookupTable) { + + private static final long serialVersionUID = 1L; + + @Override + public Iterator getIterator(String input) { + return (Iterator) prepareAutoCompleteList(input, lookupTable, panelCtx.getPageBase().getLocalizationService()).iterator(); + } + }; + } + + protected List prepareAutoCompleteList(String input, LookupTableType lookupTable, LocalizationService localizationService) { + return WebComponentUtil.prepareAutoCompleteList(lookupTable, input, localizationService); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ThreeStateComboPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ThreeStateComboPanelFactory.java new file mode 100644 index 00000000000..cc187a63362 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/ThreeStateComboPanelFactory.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.panel; + +import javax.annotation.PostConstruct; + +import com.evolveum.midpoint.web.component.prism.InputPanel; + +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.util.DOMUtil; +import com.evolveum.midpoint.web.component.input.TriStateComboPanel; + +/** + * @author katka + * + */ +@Component +public class ThreeStateComboPanelFactory extends AbstractInputGuiComponentFactory { + + @PostConstruct + public void register() { + getRegistry().addToRegistry(this); + } + + @Override + public boolean match(IW wrapper) { + return DOMUtil.XSD_BOOLEAN.equals(wrapper.getTypeName()); + } + + @Override + protected InputPanel getPanel(PrismPropertyPanelContext panelCtx) { + return new TriStateComboPanel(panelCtx.getComponentId(), panelCtx.getRealValueModel()); + } + + + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/UploadDownloadPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/UploadDownloadPanelFactory.java similarity index 70% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/UploadDownloadPanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/UploadDownloadPanelFactory.java index 75e4498d11b..202e78c2358 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/UploadDownloadPanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/UploadDownloadPanelFactory.java @@ -4,7 +4,7 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import java.io.ByteArrayInputStream; import java.io.InputStream; @@ -12,16 +12,13 @@ import javax.annotation.PostConstruct; +import com.evolveum.midpoint.web.component.prism.InputPanel; + import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.markup.html.panel.Panel; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.web.component.input.UploadDownloadPanel; @@ -29,16 +26,13 @@ * @author katkav * */ +//FIXME serializable @Component -public class UploadDownloadPanelFactory extends AbstractGuiComponentFactory implements Serializable { - - private static final long serialVersionUID = 1L; - - @Autowired private transient GuiComponentRegistry registry; +public class UploadDownloadPanelFactory extends AbstractInputGuiComponentFactory implements Serializable { @PostConstruct public void register() { - registry.addToRegistry(this); + getRegistry().addToRegistry(this); } @Override @@ -47,7 +41,7 @@ public boolean match(IW wrapper) { } @Override - protected Panel getPanel(PrismPropertyPanelContext panelCtx) { + protected InputPanel getPanel(PrismPropertyPanelContext panelCtx) { return new UploadDownloadPanel(panelCtx.getComponentId(), false) { //getModel().getObject().isReadonly() private static final long serialVersionUID = 1L; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/VariableBindingDefinitionTypePanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/VariableBindingDefinitionTypePanelFactory.java similarity index 91% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/VariableBindingDefinitionTypePanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/VariableBindingDefinitionTypePanelFactory.java index a0122f3df85..a7f5cbae6f5 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/VariableBindingDefinitionTypePanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/VariableBindingDefinitionTypePanelFactory.java @@ -4,10 +4,10 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.impl.component.VariableBindingDefinitionTypePanel; import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.VariableBindingDefinitionType; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/WorkItemDetailsPanelFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/WorkItemDetailsPanelFactory.java similarity index 74% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/WorkItemDetailsPanelFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/WorkItemDetailsPanelFactory.java index 26de9e22037..a6f033b64d9 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/WorkItemDetailsPanelFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/panel/WorkItemDetailsPanelFactory.java @@ -4,16 +4,14 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.panel; import com.evolveum.midpoint.gui.api.factory.AbstractGuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.component.PolyStringEditorPanel; -import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.web.page.admin.workflow.WorkItemDetailsPanel; import com.evolveum.midpoint.xml.ns._public.common.common_3.CaseWorkItemType; -import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; + import org.apache.wicket.markup.html.panel.Panel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -26,14 +24,9 @@ @Component public class WorkItemDetailsPanelFactory extends AbstractGuiComponentFactory { - private static final long serialVersionUID = 1L; - - @Autowired - GuiComponentRegistry registry; - @PostConstruct public void register() { - registry.addToRegistry(this); + getRegistry().addToRegistry(this); } @Override diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/AppendersWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/AppendersWrapperFactoryImpl.java similarity index 60% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/AppendersWrapperFactoryImpl.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/AppendersWrapperFactoryImpl.java index 870c679e24d..ddcabcbc864 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/AppendersWrapperFactoryImpl.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/AppendersWrapperFactoryImpl.java @@ -4,20 +4,18 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; - +package com.evolveum.midpoint.gui.impl.factory.wrapper; import java.util.List; import org.springframework.stereotype.Component; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.prism.ComplexTypeDefinition; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.util.QNameUtil; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AppenderConfigurationType; /** @@ -25,7 +23,7 @@ * */ @Component -public class AppendersWrapperFactoryImpl extends PrismContainerWrapperFactoryImpl{ +public class AppendersWrapperFactoryImpl extends PrismContainerWrapperFactoryImpl { @Override public boolean match(ItemDefinition def) { @@ -40,10 +38,24 @@ public int getOrder() { @Override protected List getItemDefinitions(PrismContainerWrapper parent, PrismContainerValue value) { - if(value != null && value.getComplexTypeDefinition() != null - && value.getComplexTypeDefinition().getDefinitions() != null) { - return value.getComplexTypeDefinition().getDefinitions(); + List defs = getComplexTypeDefinitions(value); + if (defs != null) { + return defs; } + return parent.getDefinitions(); } + + private List getComplexTypeDefinitions(PrismContainerValue value) { + if (value == null) { + return null; + } + + ComplexTypeDefinition ctd = value.getComplexTypeDefinition(); + if (ctd == null) { + return null; + } + + return ctd.getDefinitions(); + } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/AssignmentDetailsWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/AssignmentDetailsWrapperFactoryImpl.java similarity index 86% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/AssignmentDetailsWrapperFactoryImpl.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/AssignmentDetailsWrapperFactoryImpl.java index 37f19908c2a..247c6a88cda 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/AssignmentDetailsWrapperFactoryImpl.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/AssignmentDetailsWrapperFactoryImpl.java @@ -4,16 +4,16 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.wrapper; import javax.xml.namespace.QName; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import org.springframework.stereotype.Component; import com.evolveum.midpoint.gui.api.prism.ItemStatus; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.MappingsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.PersonaConstructionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyRuleType; @@ -33,10 +33,7 @@ public boolean match(ItemDefinition def) { @Override protected boolean canCreateWrapper(ItemDefinition def, ItemStatus status, WrapperContext context, boolean isEmptyValue) { - if (!isEmptyValue){ - return true; - } - return false; + return !isEmptyValue; } @Override diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/CaseWorkItemWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/CaseWorkItemWrapperFactoryImpl.java new file mode 100644 index 00000000000..fa9ae2f1d4c --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/CaseWorkItemWrapperFactoryImpl.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.wrapper; + +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.web.page.admin.workflow.WorkItemDetailsPanel; +import com.evolveum.midpoint.xml.ns._public.common.common_3.CaseWorkItemType; + +/** + * Created by honchar + */ +@Component +public class CaseWorkItemWrapperFactoryImpl extends NoEmptyValueContainerWrapperFactoryImpl { + + @Override + public boolean match(ItemDefinition def) { + return CaseWorkItemType.COMPLEX_TYPE.equals(def.getTypeName()); + } + + @Override + public void register() { + getRegistry().addToRegistry(this); + } + + @Override + public int getOrder() { + return super.getOrder() - 10; + } + + @Override + public void registerWrapperPanel(PrismContainerWrapper wrapper) { + getRegistry().registerWrapperPanel(wrapper.getTypeName(), WorkItemDetailsPanel.class); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ClassLoggerWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ClassLoggerWrapperFactoryImpl.java similarity index 95% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ClassLoggerWrapperFactoryImpl.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ClassLoggerWrapperFactoryImpl.java index 917bf5fa9d2..7f6927599fd 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ClassLoggerWrapperFactoryImpl.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ClassLoggerWrapperFactoryImpl.java @@ -4,7 +4,7 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.wrapper; import org.springframework.stereotype.Component; @@ -35,4 +35,6 @@ protected boolean canCreateValueWrapper(PrismContainerValue value) { } return !loggerPackage.equals(ProfilingClassLoggerWrapperFactoryImpl.LOGGER_PROFILING); } + + } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ConnectorConfigurationWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ConnectorConfigurationWrapperFactoryImpl.java similarity index 90% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ConnectorConfigurationWrapperFactoryImpl.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ConnectorConfigurationWrapperFactoryImpl.java index 599f0cd9af2..c3b04009c7c 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ConnectorConfigurationWrapperFactoryImpl.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ConnectorConfigurationWrapperFactoryImpl.java @@ -5,18 +5,18 @@ * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.wrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.xml.ns._public.common.common_3.ConnectorConfigurationType; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; @Component public class ConnectorConfigurationWrapperFactoryImpl extends PrismContainerWrapperFactoryImpl { @@ -43,7 +43,7 @@ protected List getItemDefinitions(PrismContainerWrappe relevantDefinitions.add((PrismContainerDefinition) def); } } - Collections.sort(relevantDefinitions, (o1, o2) -> { + relevantDefinitions.sort((o1, o2) -> { int ord1 = o1.getDisplayOrder() != null ? o1.getDisplayOrder() : Integer.MAX_VALUE; int ord2 = o2.getDisplayOrder() != null ? o2.getDisplayOrder() : Integer.MAX_VALUE; return Integer.compare(ord1, ord2); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ConstructionWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ConstructionWrapperFactory.java similarity index 75% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ConstructionWrapperFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ConstructionWrapperFactory.java index b537fedcfbd..d6a5d140890 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ConstructionWrapperFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ConstructionWrapperFactory.java @@ -4,12 +4,14 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.wrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.impl.prism.ConstructionValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.model.api.ModelService; +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.impl.prism.wrapper.ConstructionValueWrapper; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.PrismObject; @@ -22,16 +24,12 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; @Component public class ConstructionWrapperFactory extends AssignmentDetailsWrapperFactoryImpl { private static final Trace LOGGER = TraceManager.getTrace(ConstructionWrapperFactory.class); - @Autowired private ModelService model; - @Override public int getOrder() { return super.getOrder() - 10; @@ -55,19 +53,25 @@ public PrismContainerValueWrapper createContainerValueWrapper( } } + setupResource(constructionValueWrapper, constructionType, context); + return constructionValueWrapper; + } + private void setupResource(ConstructionValueWrapper constructionValueWrapper, ConstructionType constructionType, WrapperContext context) { ObjectReferenceType resourceRef = constructionType.getResourceRef(); + if (resourceRef == null) { + return; + } - PrismObject resource = null; + PrismObject resource; try { - resource = model.getObject(ResourceType.class, resourceRef.getOid(), SelectorOptions.createCollection(GetOperationOptions.createNoFetch()), context.getTask(), context.getResult()); + resource = getModelService().getObject(ResourceType.class, resourceRef.getOid(), SelectorOptions.createCollection(GetOperationOptions.createNoFetch()), context.getTask(), context.getResult()); } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | CommunicationException | ConfigurationException | ExpressionEvaluationException e) { LOGGER.error("Problem occurred during resolving resource, reason: {}", e.getMessage(), e); context.getResult().recordFatalError("A problem occurred during resolving resource, reason: " + e.getMessage(), e); - return constructionValueWrapper; + return; } constructionValueWrapper.setResource(resource); - return constructionValueWrapper; } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ExpressionWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ExpressionWrapperFactory.java new file mode 100644 index 00000000000..361f0d1096b --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ExpressionWrapperFactory.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.wrapper; + +import com.evolveum.midpoint.gui.api.prism.ItemStatus; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.impl.prism.panel.ExpressionPropertyPanel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.PrismProperty; +import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.midpoint.gui.impl.prism.wrapper.ExpressionWrapper; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType; + +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +/** + * Created by honchar + */ +@Component +public class ExpressionWrapperFactory extends PrismPropertyWrapperFactoryImpl { + + @Override + public boolean match(ItemDefinition def) { + return QNameUtil.match(ExpressionType.COMPLEX_TYPE, def.getTypeName()); + } + + @PostConstruct + @Override + public void register() { + getRegistry().addToRegistry(this); + } + + @Override + public int getOrder() { + return 100; + } + + @Override + protected PrismPropertyWrapper createWrapperInternal(PrismContainerValueWrapper parent, PrismProperty item, + ItemStatus status, WrapperContext ctx) { + + ExpressionWrapper expressionWrapper = new ExpressionWrapper(parent, item, status); + if (!expressionWrapper.isConstructionExpression() && !expressionWrapper.isAttributeExpression() && !expressionWrapper.isAssociationExpression()) { + return super.createWrapperInternal(parent, item, status, ctx); + } + + return expressionWrapper; + } + + @Override + public void registerWrapperPanel(PrismPropertyWrapper wrapper) { + if (!(wrapper instanceof ExpressionWrapper)) { + super.registerWrapperPanel(wrapper); + return; + } + ExpressionWrapper expressionWrapper = (ExpressionWrapper) wrapper; + if (expressionWrapper.isConstructionExpression() || expressionWrapper.isAttributeExpression() || expressionWrapper.isAssociationExpression()) { + getRegistry().registerWrapperPanel(expressionWrapper.getTypeName(), ExpressionPropertyPanel.class); + return; + } + + super.registerWrapperPanel(wrapper); + + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/HeterogenousContainerWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/HeterogenousContainerWrapperFactory.java new file mode 100644 index 00000000000..0cc9f965023 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/HeterogenousContainerWrapperFactory.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.wrapper; + +import java.util.List; +import java.util.stream.Collectors; +import javax.annotation.PostConstruct; +import javax.xml.namespace.QName; + +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.web.component.prism.ValueStatus; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractPolicyConstraintType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskPartitionsDefinitionType; + +/** + * @author katka + */ +@Component +public class HeterogenousContainerWrapperFactory extends PrismContainerWrapperFactoryImpl { + + @Override + public PrismContainerValueWrapper createValueWrapper(PrismContainerWrapper parent, + PrismContainerValue value, ValueStatus status, WrapperContext context) + throws SchemaException { + PrismContainerValueWrapper containerValueWrapper = super.createValueWrapper(parent, value, status, context); + containerValueWrapper.setHeterogenous(true); + return containerValueWrapper; + } + + @Override + protected List getItemDefinitions(PrismContainerWrapper parent, PrismContainerValue value) { + return parent.getDefinitions().stream().filter(def -> filterDefinitins(value, def)).collect(Collectors.toList()); + } + + private boolean filterDefinitins(PrismContainerValue value, ItemDefinition def) { + Item child = value.findItem(def.getItemName()); + return (child != null && !child.isEmpty()) || !(def instanceof PrismContainerDefinition); + } + + /** + * + * match single value containers which contains a looot of other conainers, e.g. policy rule, policy action, notification configuration, etc + */ + @Override + public boolean match(ItemDefinition def) { + QName defName = def.getTypeName(); + + if (TaskPartitionsDefinitionType.COMPLEX_TYPE.equals(defName)) { + return true; + } + + if (!(def instanceof PrismContainerDefinition)) { + return false; + } + + PrismContainerDefinition containerDef = (PrismContainerDefinition) def; + + if (containerDef.isMultiValue() && isNotPolicyConstraint(containerDef)) { + return false; + } + + List defs = containerDef.getDefinitions(); + int containers = 0; + for (ItemDefinition itemDef : defs) { + if (itemDef instanceof PrismContainerDefinition && itemDef.isMultiValue()) { + containers++; + } + } + + return containers > 2; + + } + + private boolean isNotPolicyConstraint(PrismContainerDefinition containerDef) { + if (containerDef.getCompileTimeClass() == null) { + return true; + } + + return !AbstractPolicyConstraintType.class.isAssignableFrom(containerDef.getCompileTimeClass()); + } + + @Override + @PostConstruct + public void register() { + getRegistry().addToRegistry(this); + } + + @Override + public int getOrder() { + return 110; + } + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ItemWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ItemWrapperFactoryImpl.java similarity index 71% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ItemWrapperFactoryImpl.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ItemWrapperFactoryImpl.java index a8f3bbf7e9f..070a244387a 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ItemWrapperFactoryImpl.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ItemWrapperFactoryImpl.java @@ -4,24 +4,30 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.wrapper; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import com.evolveum.midpoint.gui.api.factory.wrapper.ItemWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.model.api.ModelService; + +import com.evolveum.midpoint.prism.path.ItemName; +import com.evolveum.midpoint.task.api.TaskManager; + import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; import com.evolveum.midpoint.gui.impl.registry.GuiComponentRegistryImpl; import com.evolveum.midpoint.model.api.ModelInteractionService; import com.evolveum.midpoint.prism.*; -import com.evolveum.midpoint.prism.path.ItemName; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.SchemaException; @@ -37,29 +43,25 @@ * @author katka * */ -public abstract class ItemWrapperFactoryImpl implements ItemWrapperFactory { +public abstract class ItemWrapperFactoryImpl implements ItemWrapperFactory { private static final Trace LOGGER = TraceManager.getTrace(ItemWrapperFactoryImpl.class); @Autowired private GuiComponentRegistryImpl registry; @Autowired private PrismContext prismContext; @Autowired private ModelInteractionService modelInteractionService; + @Autowired private ModelService modelService; + @Autowired private TaskManager taskManager; + @SuppressWarnings("unchecked") @Override public IW createWrapper(PrismContainerValueWrapper parent, ItemDefinition def, WrapperContext context) throws SchemaException { ItemName name = def.getItemName(); - I childItem = null; - ItemStatus status = null; - if (CollectionUtils.isNotEmpty(context.getVirtualItemSpecification())) { - childItem = (I) def.instantiate(); - status = ItemStatus.NOT_CHANGED; - } else { - childItem = (I) parent.getNewValue().findItem(name); - status = getStatus(childItem); - } + I childItem = (I) parent.getNewValue().findItem(name); + ItemStatus status = getStatus(childItem); - if (!skipCreateWrapper(def, status, context, childItem == null || CollectionUtils.isEmpty(childItem.getValues()))) { + if (skipCreateWrapper(def, status, context, childItem == null || CollectionUtils.isEmpty(childItem.getValues()))) { LOGGER.trace("Skipping creating wrapper for non-existent item. It is not supported for {}", def); return null; } @@ -68,7 +70,7 @@ public IW createWrapper(PrismContainerValueWrapper parent, ItemDefinition childItem = (I) parent.getNewValue().findOrCreateItem(name); } - return createCompleteWrapper(parent, childItem, status, context); + return createWrapper(parent, childItem, status, context); } private ItemStatus getStatus(I childItem) { @@ -80,14 +82,22 @@ private ItemStatus getStatus(I childItem) { } + public abstract void registerWrapperPanel(IW wrapper); - public IW createWrapper(Item childItem, ItemStatus status, WrapperContext context) throws SchemaException { - return createCompleteWrapper(null, (I) childItem, status, context); + @SuppressWarnings("unchecked") + public IW createWrapper(PrismContainerValueWrapper parent, Item childItem, ItemStatus status, WrapperContext context) throws SchemaException { + ItemDefinition def = childItem.getDefinition(); + if (skipCreateWrapper(def, status, context, CollectionUtils.isEmpty(childItem.getValues()))) { + LOGGER.trace("Skipping creating wrapper for non-existent item. It is not supported for {}", def); + if (parent != null && parent.getNewValue() != null) { + parent.getNewValue().remove(childItem); + } + return null; + } - } + IW itemWrapper = createWrapperInternal(parent, (I) childItem, status, context); - private IW createCompleteWrapper(PrismContainerValueWrapper parent, I childItem, ItemStatus status, WrapperContext context) throws SchemaException { - IW itemWrapper = createWrapper(parent, childItem, status, context); + registerWrapperPanel(itemWrapper); List valueWrappers = createValuesWrapper(itemWrapper, (I) childItem, context); itemWrapper.getValues().addAll(valueWrappers); @@ -102,76 +112,49 @@ private IW createCompleteWrapper(PrismContainerValueWrapper parent, I childIt setupWrapper(itemWrapper); return itemWrapper; - } - - protected abstract void setupWrapper(IW wrapper); - - protected > List createValuesWrapper(IW itemWrapper, I item, WrapperContext context) throws SchemaException { - List pvWrappers = new ArrayList<>(); - - ID definition = (ID) item.getDefinition(); - - //TODO : prismContainer.isEmpty() interates and check is all prismcontainervalues are empty.. isn't it confusing? - if (item.isEmpty() && item.getValues().isEmpty()) { - if (shouldCreateEmptyValue(item, context)) { - PV prismValue = createNewValue(item); - VW valueWrapper = createValueWrapper(itemWrapper, prismValue, ValueStatus.ADDED, context); - pvWrappers.add(valueWrapper); - } - return pvWrappers; - } - - for (PV pcv : (List)item.getValues()) { - if(canCreateValueWrapper(pcv)){ - VW valueWrapper = createValueWrapper(itemWrapper, pcv, ValueStatus.NOT_CHANGED, context); - pvWrappers.add(valueWrapper); - } - } - - return pvWrappers; } private boolean skipCreateWrapper(ItemDefinition def, ItemStatus status, WrapperContext context, boolean isEmptyValue) { if (QNameUtil.match(FocusType.F_LINK_REF, def.getItemName()) || QNameUtil.match(FocusType.F_PERSONA_REF, def.getItemName())) { LOGGER.trace("Skip creating wrapper for {}, it is not supported", def); - return false; + return true; } if (ItemProcessing.IGNORE == def.getProcessing()) { LOGGER.trace("Skip creating wrapper for {}, because item processig is set to IGNORE.", def); - return false; + return true; } - if (def.isExperimental() && !WebModelServiceUtils.isEnableExperimentalFeature(modelInteractionService, context.getTask(), context.getResult())) { + if (def.isExperimental() && !WebModelServiceUtils.isEnableExperimentalFeature(getModelInteractionService(), context.getTask(), context.getResult())) { LOGGER.trace("Skipping creating wrapper for {}, because experimental GUI features are turned off.", def); - return false; + return true; } if (ItemStatus.ADDED == status && def.isDeprecated()) { - LOGGER.trace("Skipping creating wrapeer for {}, because item is deprecated and doesn't contain any value.", def); - return false; + LOGGER.trace("Skipping creating wrapper for {}, because item is deprecated and doesn't contain any value.", def); + return true; } if (ItemStatus.ADDED == context.getObjectStatus() && !def.canAdd()) { LOGGER.trace("Skipping creating wrapper for {}, because ADD operation is not supported.", def); - return false; + return true; } if (ItemStatus.NOT_CHANGED == context.getObjectStatus()) { if (!def.canRead()) { LOGGER.trace("Skipping creating wrapper for {}, because read operation is not supported.", def); - return false; + return true; } } - return canCreateWrapper(def, status, context, isEmptyValue); + return !canCreateWrapper(def, status, context, isEmptyValue); } protected boolean canCreateWrapper(ItemDefinition def, ItemStatus status, WrapperContext context, boolean isEmptyValue) { - if (!context.isCreateOperational() && def.isOperational()) { + if (def.isOperational()) { LOGGER.trace("Skipping creating wrapper for {}, because it is operational.", def.getItemName()); return false; } @@ -179,12 +162,43 @@ protected boolean canCreateWrapper(ItemDefinition def, ItemStatus status, Wra return true; } + + protected abstract void setupWrapper(IW wrapper); + + protected List createValuesWrapper(IW itemWrapper, I item, WrapperContext context) throws SchemaException { + List pvWrappers = new ArrayList<>(); + + List values = getValues(item); + if (values.isEmpty()) { + if (shouldCreateEmptyValue(item, context)) { + PV prismValue = createNewValue(item); + VW valueWrapper = createValueWrapper(itemWrapper, prismValue, ValueStatus.ADDED, context); + pvWrappers.add(valueWrapper); + } + return pvWrappers; + } + + for (PV pcv : values) { + if(canCreateValueWrapper(pcv)){ + VW valueWrapper = createValueWrapper(itemWrapper, pcv, ValueStatus.NOT_CHANGED, context); + pvWrappers.add(valueWrapper); + } + } + + return pvWrappers; + + } + + protected List getValues(I item) { + return item.getValues(); + } + private boolean determineReadOnly(IW itemWrapper, WrapperContext context) { Boolean readOnly = context.getReadOnly(); if (readOnly != null) { LOGGER.trace("Setting {} as readonly because context said so.", itemWrapper); - return readOnly.booleanValue(); + return readOnly; } ItemStatus objectStatus = context.getObjectStatus(); @@ -230,7 +244,7 @@ protected boolean canCreateValueWrapper(PV pcv) { protected abstract PV createNewValue(I item) throws SchemaException; - protected abstract IW createWrapper(PrismContainerValueWrapper parent, I childContainer, ItemStatus status, WrapperContext wrapperContext); + protected abstract IW createWrapperInternal(PrismContainerValueWrapper parent, I childContainer, ItemStatus status, WrapperContext wrapperContext); protected boolean shouldCreateEmptyValue(I item, WrapperContext context) { if (item.getDefinition().isEmphasized()) { @@ -258,11 +272,15 @@ public PrismContext getPrismContext() { return prismContext; } + public ModelService getModelService() { + return modelService; + } -// @Override -// public VW createValueWrapper(PV value, IW parent, ValueStatus status, WrapperContext context) throws SchemaException { -// // TODO Auto-generated method stub -// return null; -// } + public TaskManager getTaskManager() { + return taskManager; + } + public ModelInteractionService getModelInteractionService() { + return modelInteractionService; + } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/LoggingAppenderWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/LoggingAppenderWrapperFactoryImpl.java new file mode 100644 index 00000000000..1c1755538f6 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/LoggingAppenderWrapperFactoryImpl.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.wrapper; + +import java.util.List; + +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; + +/** + * @author skublik + * + */ +@Component +public class LoggingAppenderWrapperFactoryImpl extends PrismPropertyWrapperFactoryImpl{ + + @Override + public boolean match(ItemDefinition def) { + return def instanceof PrismPropertyDefinition + && QNameUtil.match(def.getItemName(), ClassLoggerConfigurationType.F_APPENDER); + } + + @Override + public int getOrder() { + return super.getOrder() - 10; + } + + @Override + protected LookupTableType getPredefinedValues(PrismProperty item, WrapperContext wrapperContext) { + PrismContainerValue parent = item.getParent(); + if (parent == null || parent.getParent() == null) { + return null; + } + + //TODO change matchMethid to be able to check path istead of def??? + PrismContainerable parentParent = parent.getParent(); + if (!(parentParent instanceof PrismContainer)) { + return null; + } + + PrismContainerValue parentValue = ((PrismContainer) parentParent).getParent(); + + if(parentValue == null || isNotLoggingConfiguration(parentValue)) { + throw new IllegalArgumentException("LoggingConfigurationType not found in parent for Appender"); + } + + LoggingConfigurationType loggingConfig = parentValue.getRealValue(); + + LookupTableType lookupTable = new LookupTableType(); + List list = lookupTable.createRowList(); + for (AppenderConfigurationType appender : loggingConfig.getAppender()) { + LookupTableRowType row = new LookupTableRowType(); + String name = appender.getName(); + row.setKey(name); + row.setValue(name); + row.setLabel(new PolyStringType(name)); + list.add(row); + } + return lookupTable; + + } + + private boolean isNotLoggingConfiguration(PrismContainerValue parentValue) { + return !(parentValue.getRealValue() instanceof LoggingConfigurationType); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/LoggingConfigurationWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/LoggingConfigurationWrapperFactoryImpl.java new file mode 100644 index 00000000000..af4f121f79b --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/LoggingConfigurationWrapperFactoryImpl.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.wrapper; + +import java.util.List; +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.ItemStatus; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismContainerValueWrapperImpl; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismContainerWrapperImpl; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.web.component.prism.ValueStatus; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ClassLoggerConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.LoggingConfigurationType; + +/** + * @author skublik + */ +@Component +public class LoggingConfigurationWrapperFactoryImpl extends PrismContainerWrapperFactoryImpl{ + + @Autowired + private ClassLoggerWrapperFactoryImpl classLoggerFactory; + @Autowired + private ProfilingClassLoggerWrapperFactoryImpl profilingClassLoggerFactory; + + @Override + public boolean match(ItemDefinition def) { + return def instanceof PrismContainerDefinition + && QNameUtil.match(def.getTypeName(), LoggingConfigurationType.COMPLEX_TYPE); + } + + @PostConstruct + @Override + public void register() { + getRegistry().addToRegistry(this); + } + + @Override + public int getOrder() { + return 10; + } + + + @Override + public void addItemWrapper(ItemDefinition def, PrismContainerValueWrapper containerValueWrapper, WrapperContext context, List> wrappers) throws SchemaException { + if (QNameUtil.match(def.getTypeName(), ClassLoggerConfigurationType.COMPLEX_TYPE)) { + wrappers.add(createClassLoggingWrapper(def, containerValueWrapper, context)); + wrappers.add(createProfilingWrapper(def, containerValueWrapper, context)); + } else { + super.addItemWrapper(def, containerValueWrapper, context, wrappers); + } + } + + private ItemWrapper createProfilingWrapper(ItemDefinition def, PrismContainerValueWrapper parent, WrapperContext context) throws SchemaException { + return profilingClassLoggerFactory.createWrapper(parent, def, context); + } + + private ItemWrapper createClassLoggingWrapper(ItemDefinition def, PrismContainerValueWrapper parent, WrapperContext context) throws SchemaException { + return classLoggerFactory.createWrapper(parent, def, context); + } + + @Override + protected PrismContainerValue createNewValue(PrismContainer item) { + return item.createNewValue(); + } + + @Override + protected PrismContainerWrapper createWrapperInternal(PrismContainerValueWrapper parent, PrismContainer childContainer, + ItemStatus status, WrapperContext ctx) { + return new PrismContainerWrapperImpl<>(parent, childContainer, status); + } + + @Override + public PrismContainerValueWrapper createContainerValueWrapper(PrismContainerWrapper objectWrapper, PrismContainerValue objectValue, ValueStatus status, WrapperContext context) { + return new PrismContainerValueWrapperImpl<>(objectWrapper, objectValue, status); + } + + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/LoggingPackageWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/LoggingPackageWrapperFactoryImpl.java similarity index 77% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/LoggingPackageWrapperFactoryImpl.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/LoggingPackageWrapperFactoryImpl.java index ec51cef65c3..7940438813e 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/LoggingPackageWrapperFactoryImpl.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/LoggingPackageWrapperFactoryImpl.java @@ -4,21 +4,16 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.wrapper; import java.util.List; - import org.apache.commons.lang3.EnumUtils; import org.springframework.stereotype.Component; -import com.evolveum.midpoint.gui.api.prism.ItemStatus; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.gui.impl.page.admin.configuration.component.ComponentLoggerType; import com.evolveum.midpoint.gui.impl.page.admin.configuration.component.StandardLoggerType; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyPanel; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapperImpl; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismProperty; import com.evolveum.midpoint.prism.PrismPropertyDefinition; @@ -45,24 +40,15 @@ public boolean match(ItemDefinition def) { @Override public int getOrder() { - return Integer.MAX_VALUE-1; + return super.getOrder() - 10; } - @Override - protected PrismPropertyWrapper createWrapper(PrismContainerValueWrapper parent, PrismProperty item, - ItemStatus status, WrapperContext ctx) { - getRegistry().registerWrapperPanel(item.getDefinition().getTypeName(), PrismPropertyPanel.class); - PrismPropertyWrapper propertyWrapper = new PrismPropertyWrapperImpl<>(parent, item, status); - propertyWrapper.setPredefinedValues(getPredefinedValues()); - return propertyWrapper; - } - private LookupTableType getPredefinedValues() { + public LookupTableType getPredefinedValues(PrismProperty item, WrapperContext wrapperContext) { LookupTableType lookupTable = new LookupTableType(); List list = lookupTable.createRowList(); - List standardLoggers = EnumUtils.getEnumList(StandardLoggerType.class); - List componentLoggers = EnumUtils.getEnumList(LoggingComponentType.class); + List standardLoggers = EnumUtils.getEnumList(StandardLoggerType.class); for(StandardLoggerType standardLogger : standardLoggers) { LookupTableRowType row = new LookupTableRowType(); row.setKey(standardLogger.getValue()); @@ -74,6 +60,8 @@ private LookupTableType getPredefinedValues() { row.setLabel(label); list.add(row); } + + List componentLoggers = EnumUtils.getEnumList(LoggingComponentType.class); for(LoggingComponentType componentLogger : componentLoggers) { LookupTableRowType row = new LookupTableRowType(); String value = ComponentLoggerType.getPackageByValue(componentLogger); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/NoEmptyValueContainerWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/NoEmptyValueContainerWrapperFactoryImpl.java new file mode 100644 index 00000000000..d4976ef1356 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/NoEmptyValueContainerWrapperFactoryImpl.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.wrapper; + +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractWorkItemOutputType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ApprovalSchemaType; + +/** + * @author katka + * + */ +@Component +public class NoEmptyValueContainerWrapperFactoryImpl extends PrismContainerWrapperFactoryImpl { + + @Override + public boolean match(ItemDefinition def) { + return def instanceof PrismContainerDefinition && def.isMultiValue() + || AbstractWorkItemOutputType.COMPLEX_TYPE.equals(def.getTypeName()) + || ApprovalSchemaType.COMPLEX_TYPE .equals(def.getTypeName()); + } + + @Override + public void register() { + getRegistry().addToRegistry(this); + } + + @Override + public int getOrder() { + return 1000; + } + + @Override + protected PrismContainerValue createNewValue(PrismContainer item) { + throw new UnsupportedOperationException("New value for multi-value container should not be created while creating wrappers."); + } + + + @Override + protected boolean shouldCreateEmptyValue(PrismContainer item, WrapperContext context) { + return false; + } + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/OperationalContainerWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/OperationalContainerWrapperFactory.java new file mode 100644 index 00000000000..53800abae53 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/OperationalContainerWrapperFactory.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.wrapper; + +import javax.annotation.PostConstruct; + +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.ItemStatus; +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.PrismContainer; +import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.MetadataType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TriggerType; + +/** + * @author katka + * + */ +@Component +public class OperationalContainerWrapperFactory extends PrismContainerWrapperFactoryImpl{ + + @Override + public boolean match(ItemDefinition def) { + return QNameUtil.match(MetadataType.COMPLEX_TYPE, def.getTypeName()) || QNameUtil.match(TriggerType.COMPLEX_TYPE, def.getTypeName()); + } + + @PostConstruct + @Override + public void register() { + getRegistry().addToRegistry(this); + } + + @Override + public int getOrder() { + return 10; + } + + @Override + protected boolean canCreateWrapper(ItemDefinition def, ItemStatus status, WrapperContext context, boolean isEmptyValue) { + return true; + } + + @Override + protected boolean shouldCreateEmptyValue(PrismContainer item, WrapperContext context) { + return false; + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismContainerWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/PrismContainerWrapperFactoryImpl.java similarity index 61% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismContainerWrapperFactoryImpl.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/PrismContainerWrapperFactoryImpl.java index a6ae489341f..21e5440ae32 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismContainerWrapperFactoryImpl.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/PrismContainerWrapperFactoryImpl.java @@ -4,24 +4,25 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.wrapper; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.annotation.PostConstruct; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import com.evolveum.midpoint.gui.api.factory.wrapper.ItemWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismContainerWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerPanel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapperImpl; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerWrapperImpl; -import com.evolveum.midpoint.gui.impl.registry.GuiComponentRegistryImpl; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.impl.prism.panel.PrismContainerPanel; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismContainerValueWrapperImpl; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismContainerWrapperImpl; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; @@ -33,12 +34,10 @@ * */ @Component -public class PrismContainerWrapperFactoryImpl extends ItemWrapperFactoryImpl, PrismContainerValue, PrismContainer, PrismContainerValueWrapper> implements PrismContainerWrapperFactory{ +public class PrismContainerWrapperFactoryImpl extends ItemWrapperFactoryImpl, PrismContainerValue, PrismContainer, PrismContainerValueWrapper> implements PrismContainerWrapperFactory { private static final Trace LOGGER = TraceManager.getTrace(PrismContainerWrapperFactoryImpl.class); - @Autowired private GuiComponentRegistryImpl registry; - @Override public boolean match(ItemDefinition def) { return def instanceof PrismContainerDefinition; @@ -47,7 +46,7 @@ public boolean match(ItemDefinition def) { @PostConstruct @Override public void register() { - registry.addToRegistry(this); + getRegistry().addToRegistry(this); } @Override @@ -60,47 +59,56 @@ public int getOrder() { public PrismContainerValueWrapper createValueWrapper(PrismContainerWrapper parent, PrismContainerValue value, ValueStatus status, WrapperContext context) throws SchemaException { PrismContainerValueWrapper containerValueWrapper = createContainerValueWrapper(parent, value, status, context); + containerValueWrapper.setExpanded(shouldBeExpanded(parent, value, context)); containerValueWrapper.setShowEmpty(context.isShowEmpty()); - List> wrappers = new ArrayList<>(); - for (ItemDefinition def : getItemDefinitions(parent, value)) { - addItemWrapper(def, containerValueWrapper, context, wrappers); - } + List> children = createChildren(parent, value, containerValueWrapper, context); - containerValueWrapper.getItems().addAll((Collection) wrappers); + containerValueWrapper.getItems().addAll((Collection) children); containerValueWrapper.setVirtualContainerItems(context.getVirtualItemSpecification()); parent.setVirtual(context.getVirtualItemSpecification() != null); - containerValueWrapper.setExpanded(shouldBeExpanded(parent, value, context)); return containerValueWrapper; } + protected List> createChildren(PrismContainerWrapper parent, PrismContainerValue value, PrismContainerValueWrapper containerValueWrapper, WrapperContext context) throws SchemaException { + List> wrappers = new ArrayList<>(); + for (ItemDefinition def : getItemDefinitions(parent, value)) { + addItemWrapper(def, containerValueWrapper, context, wrappers); + } + return wrappers; + } + protected List getItemDefinitions(PrismContainerWrapper parent, PrismContainerValue value) { return parent.getDefinitions(); } protected void addItemWrapper(ItemDefinition def, PrismContainerValueWrapper containerValueWrapper, - WrapperContext context, List> wrappers) throws SchemaException { + WrapperContext context, List> wrappers) throws SchemaException { + ItemWrapper wrapper = createChildWrapper(def, containerValueWrapper, context); + if (wrapper != null) { + wrappers.add(wrapper); + } + } + + protected ItemWrapper createChildWrapper(ItemDefinition def, PrismContainerValueWrapper containerValueWrapper, WrapperContext context) throws SchemaException { + ItemWrapperFactory factory = getChildWrapperFactory(def); + return factory.createWrapper(containerValueWrapper, def, context); + } - ItemWrapperFactory factory = registry.findWrapperFactory(def); + private ItemWrapperFactory getChildWrapperFactory(ItemDefinition def) throws SchemaException { + ItemWrapperFactory factory = getRegistry().findWrapperFactory(def); if (factory == null) { LOGGER.error("Cannot find factory for {}", def); throw new SchemaException("Cannot find factory for " + def); } LOGGER.trace("Found factory {} for {}", factory, def); + return factory; + } - ItemWrapper wrapper = factory.createWrapper(containerValueWrapper, def, context); - if (wrapper == null) { - LOGGER.trace("Null wrapper created for {}. Skipping.", def); - return; - } - - wrapper.setShowEmpty(context.isShowEmpty(), false); - wrappers.add(wrapper); - } @Override protected PrismContainerValue createNewValue(PrismContainer item) { @@ -108,15 +116,20 @@ protected PrismContainerValue createNewValue(PrismContainer item) { } @Override - protected PrismContainerWrapper createWrapper(PrismContainerValueWrapper parent, PrismContainer childContainer, + protected PrismContainerWrapper createWrapperInternal(PrismContainerValueWrapper parent, PrismContainer childContainer, ItemStatus status, WrapperContext ctx) { - registry.registerWrapperPanel(childContainer.getDefinition().getTypeName(), PrismContainerPanel.class); - return new PrismContainerWrapperImpl((PrismContainerValueWrapper) parent, childContainer, status); + + return new PrismContainerWrapperImpl<>(parent, childContainer, status); + } + + @Override + public void registerWrapperPanel(PrismContainerWrapper wrapper) { + getRegistry().registerWrapperPanel(wrapper.getTypeName(), PrismContainerPanel.class); } @Override public PrismContainerValueWrapper createContainerValueWrapper(PrismContainerWrapper objectWrapper, PrismContainerValue objectValue, ValueStatus status, WrapperContext context) { - return new PrismContainerValueWrapperImpl(objectWrapper, objectValue, status); + return new PrismContainerValueWrapperImpl<>(objectWrapper, objectValue, status); } protected boolean shouldBeExpanded(PrismContainerWrapper parent, PrismContainerValue value, WrapperContext context) { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismObjectWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/PrismObjectWrapperFactoryImpl.java similarity index 76% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismObjectWrapperFactoryImpl.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/PrismObjectWrapperFactoryImpl.java index 6f00ede7237..0a66b7a906f 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismObjectWrapperFactoryImpl.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/PrismObjectWrapperFactoryImpl.java @@ -4,11 +4,10 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.wrapper; import java.util.Collection; import java.util.List; -import java.util.stream.Collectors; import javax.annotation.PostConstruct; import javax.xml.namespace.QName; @@ -16,24 +15,26 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import com.evolveum.midpoint.gui.api.factory.wrapper.ItemWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; +import com.evolveum.midpoint.gui.api.prism.wrapper.*; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.impl.prism.*; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismObjectValueWrapperImpl; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismObjectWrapperImpl; import com.evolveum.midpoint.model.api.ModelInteractionService; -import com.evolveum.midpoint.model.api.authentication.CompiledGuiProfile; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.component.prism.ValueStatus; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AuthorizationPhaseType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.DisplayType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.VirtualContainersSpecificationType; /** * @author katka @@ -43,14 +44,9 @@ public class PrismObjectWrapperFactoryImpl extends PrismCo private static final Trace LOGGER = TraceManager.getTrace(PrismObjectWrapperFactoryImpl.class); - private static final String DOT_CLASS = PrismObjectWrapperFactoryImpl.class.getName() + "."; - private static final QName VIRTUAL_CONTAINER_COMPLEX_TYPE = new QName("VirtualContainerType"); private static final QName VIRTUAL_CONTAINER = new QName("virtualContainer"); - @Autowired private GuiComponentRegistry registry; - @Autowired protected ModelInteractionService modelInteractionService; - public PrismObjectWrapper createObjectWrapper(PrismObject object, ItemStatus status, WrapperContext context) throws SchemaException { try { @@ -64,19 +60,19 @@ public PrismObjectWrapper createObjectWrapper(PrismObject object, ItemStat } context.setObject(object); - Collection virtualContainers = modelInteractionService.determineVirtualContainers(object, context.getTask(), context.getResult()); + Collection virtualContainers = getModelInteractionService().determineVirtualContainers(object, context.getTask(), context.getResult()); context.setVirtualContainers(virtualContainers); PrismObjectWrapper objectWrapper = createObjectWrapper(object, status); if (context.getReadOnly() != null) { - objectWrapper.setReadOnly(context.getReadOnly().booleanValue()); + objectWrapper.setReadOnly(context.getReadOnly()); } context.setShowEmpty(ItemStatus.ADDED == status); objectWrapper.setExpanded(true); PrismContainerValueWrapper valueWrapper = createValueWrapper(objectWrapper, object.getValue(), ItemStatus.ADDED == status ? ValueStatus.ADDED : ValueStatus.NOT_CHANGED, context); objectWrapper.getValues().add(valueWrapper); + registerWrapperPanel(objectWrapper); - registry.registerWrapperPanel(object.getDefinition().getTypeName(), PrismContainerPanel.class); return objectWrapper; } @@ -93,7 +89,7 @@ public void updateWrapper(PrismObjectWrapper wrapper, WrapperContext context) } context.setObject(wrapper.getObject()); - Collection virtualContainers = modelInteractionService.determineVirtualContainers(wrapper.getObject(), context.getTask(), context.getResult()); + Collection virtualContainers = getModelInteractionService().determineVirtualContainers(wrapper.getObject(), context.getTask(), context.getResult()); context.setVirtualContainers(virtualContainers); context.setShowEmpty(ItemStatus.ADDED == wrapper.getStatus()); wrapper.setExpanded(true); @@ -104,16 +100,16 @@ public void updateWrapper(PrismObjectWrapper wrapper, WrapperContext context) wrapper.getValues().clear(); wrapper.getValues().add(valueWrapper); - registry.registerWrapperPanel(wrapper.getObject().getDefinition().getTypeName(), PrismContainerPanel.class); + registerWrapperPanel(wrapper); } @Override public PrismObjectValueWrapper createContainerValueWrapper(PrismContainerWrapper objectWrapper, PrismContainerValue objectValue, ValueStatus status, WrapperContext context) { - return new PrismObjectValueWrapperImpl((PrismObjectWrapper) objectWrapper, (PrismObjectValue) objectValue, status); + return new PrismObjectValueWrapperImpl<>((PrismObjectWrapper) objectWrapper, (PrismObjectValue) objectValue, status); } public PrismObjectWrapper createObjectWrapper(PrismObject object, ItemStatus status) { - return new PrismObjectWrapperImpl(object, status); + return new PrismObjectWrapperImpl<>(object, status); } @Override @@ -134,12 +130,12 @@ public PrismContainerValueWrapper createValueWrapper(PrismContainerWrapper mCtd.setHelp(WebComponentUtil.getOrigStringFromPoly(display.getHelp())); mCtd.setRuntimeSchema(true); - MutablePrismContainerDefinition def = getPrismContext().definitionFactory().createContainerDefinition(VIRTUAL_CONTAINER, mCtd); + MutablePrismContainerDefinition def = getPrismContext().definitionFactory().createContainerDefinition(VIRTUAL_CONTAINER, mCtd); def.setMaxOccurs(1); def.setDisplayName(WebComponentUtil.getOrigStringFromPoly(display.getLabel())); def.setDynamic(true); - ItemWrapperFactory factory = getRegistry().findWrapperFactory(def); + ItemWrapperFactory factory = getRegistry().findWrapperFactory(def); if (factory == null) { LOGGER.warn("Cannot find factory for {}. Skipping wrapper creation.", def); continue; @@ -147,12 +143,16 @@ public PrismContainerValueWrapper createValueWrapper(PrismContainerWrapper WrapperContext ctx = context.clone(); ctx.setVirtualItemSpecification(virtualContainer.getItem()); - ItemWrapper iw = factory.createWrapper(objectValueWrapper, def, ctx); - iw.setVisibleOverwrite(virtualContainer.getVisibility()); + PrismContainer virtualPrismContainer = def.instantiate(); + ItemStatus virtualContainerStatus = context.getObjectStatus() != null ? context.getObjectStatus() : ItemStatus.NOT_CHANGED; + + + ItemWrapper iw = factory.createWrapper(objectValueWrapper, virtualPrismContainer, virtualContainerStatus, ctx); if (iw == null) { continue; } + iw.setVisibleOverwrite(virtualContainer.getVisibility()); ((List) objectValueWrapper.getItems()).add(iw); } @@ -169,10 +169,11 @@ protected void applySecurityConstraints(PrismObject object, WrapperContext co OperationResult result = context.getResult(); try { - PrismObjectDefinition objectDef = modelInteractionService.getEditObjectDefinition(object, phase, task, result); + PrismObjectDefinition objectDef = getModelInteractionService().getEditObjectDefinition(object, phase, task, result); object.applyDefinition(objectDef, true); } catch (SchemaException | ConfigurationException | ObjectNotFoundException | ExpressionEvaluationException | CommunicationException | SecurityViolationException e) { + LOGGER.error("Exception while applying security constraints: {}", e.getMessage(), e); throw e; } @@ -186,7 +187,7 @@ public boolean match(ItemDefinition def) { @Override @PostConstruct public void register() { - registry.addToRegistry(this); + getRegistry().addToRegistry(this); } @Override diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismPropertyWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/PrismPropertyWrapperFactoryImpl.java similarity index 71% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismPropertyWrapperFactoryImpl.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/PrismPropertyWrapperFactoryImpl.java index 8326b464f5e..506b4c6e7a0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismPropertyWrapperFactoryImpl.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/PrismPropertyWrapperFactoryImpl.java @@ -4,7 +4,7 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.wrapper; import java.util.Collection; import javax.annotation.PostConstruct; @@ -12,17 +12,20 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.gui.api.prism.ItemStatus; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.prism.*; -import com.evolveum.midpoint.model.api.ModelService; +import com.evolveum.midpoint.gui.impl.prism.panel.PrismPropertyPanel; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismPropertyValueWrapper; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismPropertyWrapperImpl; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SchemaHelper; import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.task.api.TaskManager; import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -37,9 +40,7 @@ public class PrismPropertyWrapperFactoryImpl extends ItemWrapperFactoryImpl

createNewValue(PrismProperty item) throws Sch } @Override - protected PrismPropertyWrapper createWrapper(PrismContainerValueWrapper parent, PrismProperty item, + protected PrismPropertyWrapper createWrapperInternal(PrismContainerValueWrapper parent, PrismProperty item, ItemStatus status, WrapperContext wrapperContext) { - getRegistry().registerWrapperPanel(item.getDefinition().getTypeName(), PrismPropertyPanel.class); PrismPropertyWrapper propertyWrapper = new PrismPropertyWrapperImpl<>(parent, item, status); + propertyWrapper.setPredefinedValues(getPredefinedValues(item, wrapperContext)); + return propertyWrapper; + } + + protected LookupTableType getPredefinedValues(PrismProperty item, WrapperContext wrapperContext) { PrismReferenceValue valueEnumerationRef = item.getDefinition().getValueEnumerationRef(); - if (valueEnumerationRef != null) { + if (valueEnumerationRef == null) { + return null; + } //TODO: task and result from context Task task = wrapperContext.getTask(); OperationResult result = wrapperContext.getResult().createSubresult(OPERATION_LOAD_LOOKUP_TABLE); @@ -81,24 +88,29 @@ protected PrismPropertyWrapper createWrapper(PrismContainerValueWrapper pa .createLookupTableRetrieveOptions(schemaHelper); try { - PrismObject lookupTable = modelService.getObject(LookupTableType.class, valueEnumerationRef.getOid(), options, task, result); - propertyWrapper.setPredefinedValues(lookupTable.asObjectable()); + PrismObject lookupTable = getModelService().getObject(LookupTableType.class, valueEnumerationRef.getOid(), options, task, result); result.computeStatusIfUnknown(); + return lookupTable.asObjectable(); } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | CommunicationException | ConfigurationException | ExpressionEvaluationException e) { LOGGER.error("Cannot load lookup table for {} ", item); result.recordFatalError("Cannot load lookupTable for " + item + ", Reason: " + e.getMessage(), e); //TODO throw??? } - } - return propertyWrapper; + + return null; + } @Override public PrismPropertyValueWrapper createValueWrapper(PrismPropertyWrapper parent, PrismPropertyValue value, - ValueStatus status, WrapperContext context) throws SchemaException { - PrismPropertyValueWrapper valueWrapper = new PrismPropertyValueWrapper<>(parent, value, status); - return valueWrapper; + ValueStatus status, WrapperContext context) { + return new PrismPropertyValueWrapper<>(parent, value, status); + } + + @Override + public void registerWrapperPanel(PrismPropertyWrapper wrapper) { + getRegistry().registerWrapperPanel(wrapper.getTypeName(), PrismPropertyPanel.class); } @Override diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismReferenceWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/PrismReferenceWrapperFactory.java similarity index 53% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismReferenceWrapperFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/PrismReferenceWrapperFactory.java index 8b3ca008cc5..210a094f679 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/PrismReferenceWrapperFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/PrismReferenceWrapperFactory.java @@ -4,25 +4,22 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.wrapper; import javax.annotation.PostConstruct; -import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.impl.prism.panel.PrismReferencePanel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismReferenceValueWrapperImpl; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismReferenceWrapper; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismReferenceWrapperImpl; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.CaseType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; + import org.springframework.stereotype.Component; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyPanel; -import com.evolveum.midpoint.gui.impl.prism.PrismReferencePanel; -import com.evolveum.midpoint.gui.impl.prism.PrismReferenceValueWrapperImpl; -import com.evolveum.midpoint.gui.impl.prism.PrismReferenceWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismReferenceWrapperImpl; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismReference; import com.evolveum.midpoint.prism.PrismReferenceDefinition; @@ -30,7 +27,6 @@ import com.evolveum.midpoint.prism.Referencable; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.web.component.prism.ValueStatus; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; /** * @author katka @@ -58,39 +54,31 @@ public int getOrder() { } @Override - protected PrismReferenceValue createNewValue(PrismReference item) throws SchemaException { + protected PrismReferenceValue createNewValue(PrismReference item) { PrismReferenceValue prv = getPrismContext().itemFactory().createReferenceValue(); item.getValues().add(prv); return prv; } @Override - protected PrismReferenceWrapper createWrapper(PrismContainerValueWrapper parent, PrismReference item, + protected PrismReferenceWrapper createWrapperInternal(PrismContainerValueWrapper parent, PrismReference item, ItemStatus status, WrapperContext ctx) { - PrismReferenceWrapperImpl wrapper = new PrismReferenceWrapperImpl<>(parent, item, status); - getRegistry().registerWrapperPanel(item.getDefinition().getTypeName(), PrismReferencePanel.class); - return wrapper; + + return new PrismReferenceWrapperImpl<>(parent, item, status); } @Override public PrismReferenceValueWrapperImpl createValueWrapper(PrismReferenceWrapper parent, PrismReferenceValue value, ValueStatus status, - WrapperContext context) throws SchemaException { + WrapperContext context) { - PrismReferenceValueWrapperImpl refValue = new PrismReferenceValueWrapperImpl<>(parent, value, status); - return refValue; + return new PrismReferenceValueWrapperImpl<>(parent, value, status); } -// @Override -// protected boolean canCreateNewWrapper(ItemDefinition def) { -// //TODO compare full path instead of def.getName(). The issue is, that another complex type can have targetRef or target specified and then -// // it won't be created either in that case. -// if (AssignmentType.F_TARGET.equivalent(def.getName()) || AssignmentType.F_TARGET_REF.equivalent(def.getName())) { -// return false; -// } -// -// return true; -// } + @Override + public void registerWrapperPanel(PrismReferenceWrapper wrapper) { + getRegistry().registerWrapperPanel(wrapper.getTypeName(), PrismReferencePanel.class); + } @Override protected void setupWrapper(PrismReferenceWrapper wrapper) { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ProfilingClassLoggerWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ProfilingClassLoggerWrapperFactoryImpl.java new file mode 100644 index 00000000000..aefaea9f723 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ProfilingClassLoggerWrapperFactoryImpl.java @@ -0,0 +1,97 @@ +/* +\ * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.wrapper; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import javax.xml.namespace.QName; + +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.ItemStatus; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.impl.prism.panel.ProfilingClassLoggerPanel; +import com.evolveum.midpoint.gui.impl.prism.wrapper.ProfilingClassLoggerContainerValueWrapperImpl; +import com.evolveum.midpoint.gui.impl.prism.wrapper.ProfilingClassLoggerContainerWrapperImpl; +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.PrismContainer; +import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.web.component.prism.ValueStatus; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ClassLoggerConfigurationType; + +/** + * @author skublik + */ +@Component +public class ProfilingClassLoggerWrapperFactoryImpl extends PrismContainerWrapperFactoryImpl { + + public static final QName PROFILING_LOGGER_PATH = new QName("profilingClassLogger"); + + public static final String LOGGER_PROFILING = "PROFILING"; + + @Override + public boolean match(ItemDefinition def) { + return false; + } + + @Override + protected PrismContainerWrapper createWrapperInternal(PrismContainerValueWrapper parent, + PrismContainer childContainer, ItemStatus status, WrapperContext ctx) { + PrismContainer clone = childContainer.clone(); + return new ProfilingClassLoggerContainerWrapperImpl<>(parent, clone, status); + } + + @Override + public void registerWrapperPanel(PrismContainerWrapper wrapper) { + getRegistry().registerWrapperPanel(PROFILING_LOGGER_PATH, ProfilingClassLoggerPanel.class); + + } + + @Override + protected List> getValues(PrismContainer item) { + return item.getValues().stream().filter(value -> { + if(value == null || value.getRealValue() == null) { + return false; + } + String loggerPackage = ((ClassLoggerConfigurationType)value.getRealValue()).getPackage(); + if(loggerPackage == null) { + return false; + } + return loggerPackage.equals(LOGGER_PROFILING); + }).collect(Collectors.toList()); + } + + @Override + protected boolean shouldCreateEmptyValue(PrismContainer item, WrapperContext context) { + return true; + } + + @Override + protected PrismContainerValue createNewValue(PrismContainer item) { + PrismContainerValue profilingLogger = super.createNewValue(item); + profilingLogger.asContainerable().setPackage(LOGGER_PROFILING); + return profilingLogger; + } + + @Override + public PrismContainerValueWrapper createContainerValueWrapper(PrismContainerWrapper objectWrapper, + PrismContainerValue objectValue, ValueStatus status, WrapperContext context) { + + ClassLoggerConfigurationType logger = objectValue.getRealValue(); + if (logger != null) { + logger.setPackage(LOGGER_PROFILING); + } + + return new ProfilingClassLoggerContainerValueWrapperImpl(objectWrapper, objectValue, status); + } + + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ProtectedStringWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ProtectedStringWrapperFactory.java similarity index 64% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ProtectedStringWrapperFactory.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ProtectedStringWrapperFactory.java index 37abfc317cd..bd38990d2b6 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ProtectedStringWrapperFactory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ProtectedStringWrapperFactory.java @@ -4,11 +4,14 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.wrapper; import com.evolveum.midpoint.gui.api.component.password.PasswordPropertyPanel; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.impl.prism.*; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; +import com.evolveum.midpoint.gui.impl.prism.wrapper.ProtectedStringTypeWrapperImpl; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismProperty; import com.evolveum.midpoint.util.QNameUtil; @@ -40,11 +43,14 @@ public int getOrder() { } @Override - protected PrismPropertyWrapper createWrapper(PrismContainerValueWrapper parent, PrismProperty item, + protected PrismPropertyWrapper createWrapperInternal(PrismContainerValueWrapper parent, PrismProperty item, ItemStatus status, WrapperContext ctx) { - ProtectedStringTypeWrapperImpl propertyWrapper = new ProtectedStringTypeWrapperImpl(parent, item, status); - getRegistry().registerWrapperPanel(item.getDefinition().getTypeName(), PasswordPropertyPanel.class); - return propertyWrapper; + return new ProtectedStringTypeWrapperImpl(parent, item, status); } + @Override + public void registerWrapperPanel(PrismPropertyWrapper wrapper) { + getRegistry().registerWrapperPanel(wrapper.getTypeName(), PasswordPropertyPanel.class); + + } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ResourceAttributeWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ResourceAttributeWrapperFactoryImpl.java similarity index 58% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ResourceAttributeWrapperFactoryImpl.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ResourceAttributeWrapperFactoryImpl.java index 54998fd0b03..1911adabfe0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ResourceAttributeWrapperFactoryImpl.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ResourceAttributeWrapperFactoryImpl.java @@ -4,23 +4,20 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.wrapper; import javax.annotation.PostConstruct; import javax.xml.namespace.QName; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.evolveum.midpoint.common.refinery.LayerRefinedAttributeDefinition; -import com.evolveum.midpoint.common.refinery.RefinedAttributeDefinition; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.ResourceAttributeDefinitionPanel; -import com.evolveum.midpoint.gui.impl.prism.ResourceAttributeWrapper; -import com.evolveum.midpoint.gui.impl.prism.ResourceAttributeWrapperImpl; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ResourceAttributeWrapper; +import com.evolveum.midpoint.gui.impl.prism.panel.ResourceAttributeDefinitionPanel; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismPropertyValueWrapper; +import com.evolveum.midpoint.gui.impl.prism.wrapper.ResourceAttributeWrapperImpl; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismPropertyValue; import com.evolveum.midpoint.schema.processor.ResourceAttribute; @@ -35,8 +32,6 @@ @Component public class ResourceAttributeWrapperFactoryImpl extends ItemWrapperFactoryImpl, PrismPropertyValue, ResourceAttribute, PrismPropertyValueWrapper> { - @Autowired private GuiComponentRegistry registry; - @Override public boolean match(ItemDefinition def) { return def instanceof ResourceAttributeDefinition; @@ -49,15 +44,14 @@ public int getOrder() { @Override public PrismPropertyValueWrapper createValueWrapper(ResourceAttributeWrapper parent, - PrismPropertyValue value, ValueStatus status, WrapperContext context) throws SchemaException { - PrismPropertyValueWrapper valueWrapper = new PrismPropertyValueWrapper<>(parent, value, status); - return valueWrapper; + PrismPropertyValue value, ValueStatus status, WrapperContext context) { + return new PrismPropertyValueWrapper<>(parent, value, status); } @PostConstruct @Override public void register() { - registry.addToRegistry(this); + getRegistry().addToRegistry(this); } @Override @@ -73,10 +67,14 @@ protected PrismPropertyValue createNewValue(ResourceAttribute item) throws } @Override - protected ResourceAttributeWrapper createWrapper(PrismContainerValueWrapper parent, + protected ResourceAttributeWrapper createWrapperInternal(PrismContainerValueWrapper parent, ResourceAttribute childContainer, ItemStatus status, WrapperContext ctx) { - registry.registerWrapperPanel(new QName("ResourceAttributeDefinition"), ResourceAttributeDefinitionPanel.class); - ResourceAttributeWrapper propertyWrapper = new ResourceAttributeWrapperImpl<>(parent, childContainer, status); - return propertyWrapper; + return new ResourceAttributeWrapperImpl<>(parent, childContainer, status); + } + + @Override + public void registerWrapperPanel(ResourceAttributeWrapper wrapper) { + getRegistry().registerWrapperPanel(new QName("ResourceAttributeDefinition"), ResourceAttributeDefinitionPanel.class); + } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ShadowAssociationWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ShadowAssociationWrapperFactoryImpl.java new file mode 100644 index 00000000000..6162fe332c4 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ShadowAssociationWrapperFactoryImpl.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.wrapper; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; + +import com.evolveum.midpoint.web.component.prism.ValueStatus; + +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.common.refinery.RefinedAssociationDefinition; +import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; +import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; +import com.evolveum.midpoint.gui.api.prism.ItemStatus; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismReferenceWrapper; +import com.evolveum.midpoint.gui.impl.prism.wrapper.ShadowAssociationWrapperImpl; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.result.OperationResultStatus; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.midpoint.util.exception.*; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; + +/** + * @author skublik + */ +@Component +public class ShadowAssociationWrapperFactoryImpl extends PrismContainerWrapperFactoryImpl { + + private static final Trace LOGGER = TraceManager.getTrace(ShadowAssociationWrapperFactoryImpl.class); + + @Autowired private PrismReferenceWrapperFactory referenceWrapperFactory; + + private static final String CREATE_ASSOCIATION_WRAPPER = "createAssociationWrapper"; + private static final String DOT_CLASS = ShadowAssociationWrapperFactoryImpl.class.getName() + "."; + private static final String OPERATON_LOAD_RESOURCE = DOT_CLASS + "loadResource"; + + @Override + public boolean match(ItemDefinition def) { + return QNameUtil.match(def.getTypeName(), ShadowAssociationType.COMPLEX_TYPE); + } + + @Override + public int getOrder() { + return 10; + } + + @Override + protected PrismContainerWrapper createWrapperInternal(PrismContainerValueWrapper parent, PrismContainer childContainer, + ItemStatus status, WrapperContext ctx) { + + OperationResult parentResult = ctx.getResult(); + + if (isNotShadow(ctx, parentResult)) { + return super.createWrapperInternal(parent, childContainer, status, ctx); + } + + if (isNotAssociation(childContainer)) { + parentResult.recordStatus(OperationResultStatus.NOT_APPLICABLE, "Association for " + childContainer.getComplexTypeDefinition().getTypeClass() + " is not supported"); + LOGGER.debug("Association for {} is not supported", childContainer.getComplexTypeDefinition().getTypeClass()); + return super.createWrapperInternal(parent, childContainer, status, ctx); + } + + ShadowType shadow = (ShadowType) ctx.getObject().asObjectable(); + PrismObject resource = loadResource(shadow, ctx); + if (resource == null) { + return super.createWrapperInternal(parent, childContainer, status, ctx); + } + + + Collection refinedAssociationDefinitions = loadRefinedAssociationDefinitions(resource, shadow, parentResult); + + if (refinedAssociationDefinitions == null) { + return super.createWrapperInternal(parent, childContainer, status, ctx); + } + + + ShadowAssociationWrapperImpl associationWrapper = createShadowAssociationWrapper(parent, childContainer, resource, + refinedAssociationDefinitions, shadow, status, parentResult); + if (associationWrapper == null) { + return super.createWrapperInternal(parent, childContainer, status, ctx); + } + + return associationWrapper; + } + + private PrismReferenceDefinition createShadowAssocationDef(RefinedAssociationDefinition refinedAssociationDefinitions) { + MutablePrismReferenceDefinition shadowRefDef = getPrismContext() + .definitionFactory().createReferenceDefinition(refinedAssociationDefinitions.getName(), ObjectReferenceType.COMPLEX_TYPE); + shadowRefDef.toMutable().setMaxOccurs(-1); + shadowRefDef.setDisplayName(refinedAssociationDefinitions.getDisplayName()); + shadowRefDef.setTargetTypeName(ShadowType.COMPLEX_TYPE); + return shadowRefDef; + + } + + @Override + protected boolean canCreateWrapper(ItemDefinition def, ItemStatus status, WrapperContext context, boolean isEmptyValue) { + return super.canCreateWrapper(def, status, context, isEmptyValue); + } + + private PrismObject loadResource(ShadowType shadow, WrapperContext ctx) { + String resourceOid = shadow.getResourceRef().getOid(); + if (resourceOid == null) { + return null; + } + Task task = ctx.getTask(); + OperationResult result = ctx.getResult().createMinorSubresult(OPERATON_LOAD_RESOURCE); + try { + PrismObject resource = getModelService().getObject(ResourceType.class, resourceOid, null, task, result); + result.recordSuccess(); + return resource; + } catch (ObjectNotFoundException | SchemaException | ExpressionEvaluationException | ConfigurationException | CommunicationException | SecurityViolationException e) { + LOGGER.error("Cannot find resource referenced from shadow. {}", e.getMessage(), e); + result.recordPartialError("Could not find resource referenced from shadow.", e); + return null; + } + + } + + private Collection loadRefinedAssociationDefinitions(PrismObject resource, ShadowType shadow, OperationResult parentResult) { + OperationResult result = parentResult.createMinorSubresult(CREATE_ASSOCIATION_WRAPPER); + RefinedResourceSchema refinedResourceSchema; + try { + refinedResourceSchema = RefinedResourceSchema.getRefinedSchema(resource); + } catch (SchemaException e) { + LOGGER.error("Cannot get refined schema for {}, {}", resource, e.getMessage(), e); + result.recordPartialError("Could not get fined schema for " + resource, e); + return null; + } + ShadowKindType kind = shadow.getKind(); + String shadowIntent = shadow.getIntent(); + RefinedObjectClassDefinition oc = refinedResourceSchema.getRefinedDefinition(kind, shadowIntent); + if (oc == null) { + LOGGER.debug("Association for {}/{} not supported by resource {}", kind, shadowIntent, resource); + result.recordStatus(OperationResultStatus.NOT_APPLICABLE, "Association for " + kind + "/" + shadowIntent + " not supported by resource " + resource); + return null; + } + Collection refinedAssociationDefinitions = oc.getAssociationDefinitions(); + + if (CollectionUtils.isEmpty(refinedAssociationDefinitions)) { + result.recordStatus(OperationResultStatus.NOT_APPLICABLE, "Association for " + kind + "/" + shadowIntent + " not supported by resource " + resource); + LOGGER.debug("Association for {}/{} not supported by resource {}", kind, shadowIntent, resource); + return null; + } + result.computeStatusIfUnknown(); + return refinedAssociationDefinitions; + } + + private boolean isNotShadow(WrapperContext ctx, OperationResult parentResult) { + PrismObject object = ctx.getObject(); + ObjectType objectType = (ObjectType) object.asObjectable(); + if (!(objectType instanceof ShadowType)) { + parentResult.recordFatalError("Something very strange happened. Association container in the" + objectType.getClass().getSimpleName() + "?"); + return true; + } + return false; + + } + + private ShadowAssociationWrapperImpl createShadowAssociationWrapper(PrismContainerValueWrapper parent, + PrismContainer childContainer, PrismObject resource, + Collection refinedAssociationDefinitions, + ShadowType shadow, ItemStatus status, OperationResult parentResult) { + //we need to switch association wrapper to single value + //the transformation will be as following: + // we have single value ShadowAssociationType || ResourceObjectAssociationType, and from each shadowAssociationType we will create + // property - name of the property will be association type(QName) and the value will be shadowRef + PrismContainerDefinition associationDefinition = childContainer.getDefinition().clone(); + associationDefinition.toMutable().setMaxOccurs(1); + PrismContainer associationTransformed; + try { + associationTransformed = associationDefinition.instantiate(); + } catch (SchemaException e) { + parentResult.recordPartialError("Association for " + shadow.getKind() + "/" + shadow.getIntent() + " cannot be created " + resource, e); + LOGGER.error("Association for {}/{} on resource {} cannot be created: {}", shadow.getKind(), shadow.getIntent(), resource, e.getMessage(), e); + return null; + + } + ShadowAssociationWrapperImpl associationWrapper = new ShadowAssociationWrapperImpl(parent, associationTransformed, status); + + associationWrapper.setResource(resource.asObjectable()); + associationWrapper.setRefinedAssociationDefinitions(refinedAssociationDefinitions); + return associationWrapper; + } + + @Override + protected List> createValuesWrapper(PrismContainerWrapper itemWrapper, PrismContainer item, WrapperContext context) throws SchemaException { + if (!(itemWrapper instanceof ShadowAssociationWrapperImpl)) { + return super.createValuesWrapper(itemWrapper, item, context); + } + + ShadowAssociationWrapperImpl associationWrapper = (ShadowAssociationWrapperImpl) itemWrapper; + + PrismContainerValueWrapper shadowValueWrapper = createContainerValueWrapper(associationWrapper, + associationWrapper.getItem().createNewValue(), + ItemStatus.ADDED == associationWrapper.getStatus() ? ValueStatus.ADDED : ValueStatus.NOT_CHANGED, context); + + Collection shadowReferences = new ArrayList<>(); + for (RefinedAssociationDefinition def : associationWrapper.getRefinedAssociationDefinitions()) { + PrismReference shadowAss = fillInShadowReference(def, item); + + PrismReferenceWrapper shadowReference = (PrismReferenceWrapper) referenceWrapperFactory.createWrapper(shadowValueWrapper, shadowAss, shadowAss.isEmpty() ? ItemStatus.ADDED : ItemStatus.NOT_CHANGED, context); + shadowReference.setFilter(WebComponentUtil.createAssociationShadowRefFilter(def, + getPrismContext(), associationWrapper.getResource().getOid())); + shadowReferences.add(shadowReference); + } + + shadowValueWrapper.getItems().addAll((Collection) shadowReferences); + return Collections.singletonList(shadowValueWrapper); + + } + + private PrismReference fillInShadowReference(RefinedAssociationDefinition def, PrismContainer item) throws SchemaException { + PrismReferenceDefinition shadowRefDef = createShadowAssocationDef(def); + PrismReference shadowAss = shadowRefDef.instantiate(); + + for (PrismContainerValue associationValue : item.getValues()) { + ShadowAssociationType shadowAssociation = associationValue.asContainerable(); + if (shadowAssociation.getName().equals(def.getName())) { + shadowAss.add(associationValue.findReference(ShadowAssociationType.F_SHADOW_REF).getValue().clone()); + } + } + + return shadowAss; + } + + private boolean isNotAssociation(PrismContainer association) { + return association == null || association.getDefinition() == null + || !(association.getDefinition().getCompileTimeClass().equals(ShadowAssociationType.class)); + } + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ShadowAttributesWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ShadowAttributesWrapperFactoryImpl.java similarity index 61% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ShadowAttributesWrapperFactoryImpl.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ShadowAttributesWrapperFactoryImpl.java index 9ae6dfa7885..bd393441ffe 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ShadowAttributesWrapperFactoryImpl.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ShadowAttributesWrapperFactoryImpl.java @@ -4,19 +4,16 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.wrapper; -import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerPanel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerWrapperImpl; +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.impl.prism.panel.PrismContainerPanel; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.PrismContainer; import com.evolveum.midpoint.schema.processor.ResourceAttributeContainerDefinition; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAttributesType; -import org.springframework.stereotype.Component; @Component public class ShadowAttributesWrapperFactoryImpl extends PrismContainerWrapperFactoryImpl { @@ -31,10 +28,10 @@ public int getOrder() { return Integer.MAX_VALUE - 100; } + @Override - protected PrismContainerWrapper createWrapper(PrismContainerValueWrapper parent, - PrismContainer childContainer, ItemStatus status, WrapperContext ctx) { + public void registerWrapperPanel(PrismContainerWrapper wrapper) { getRegistry().registerWrapperPanel(ShadowAttributesType.COMPLEX_TYPE, PrismContainerPanel.class); - return new PrismContainerWrapperImpl<>(parent, childContainer, status); + } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ShadowWrapperFactoryImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ShadowWrapperFactoryImpl.java similarity index 71% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ShadowWrapperFactoryImpl.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ShadowWrapperFactoryImpl.java index c956b303497..332ed02748d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/ShadowWrapperFactoryImpl.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/ShadowWrapperFactoryImpl.java @@ -4,16 +4,13 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.factory; +package com.evolveum.midpoint.gui.impl.factory.wrapper; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; -import com.evolveum.midpoint.gui.impl.prism.ShadowWrapperImpl; -import com.evolveum.midpoint.model.api.ModelService; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.gui.impl.prism.wrapper.ShadowWrapperImpl; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismObjectDefinition; @@ -26,9 +23,6 @@ @Component public class ShadowWrapperFactoryImpl extends PrismObjectWrapperFactoryImpl { - @Autowired private GuiComponentRegistry registry; - @Autowired private ModelService modelService; - @Override public PrismObjectWrapper createObjectWrapper(PrismObject object, ItemStatus status) { return new ShadowWrapperImpl(object, status); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/TaskHandlerWrapperFactory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/TaskHandlerWrapperFactory.java new file mode 100644 index 00000000000..809c0fb29b7 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/factory/wrapper/TaskHandlerWrapperFactory.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2010-2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.factory.wrapper; + +import java.util.Collection; +import java.util.stream.Collectors; + +import org.apache.commons.lang.StringUtils; +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismProperty; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableRowType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; +import com.evolveum.prism.xml.ns._public.types_3.PolyStringTranslationType; +import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; + +@Component +public class TaskHandlerWrapperFactory extends PrismPropertyWrapperFactoryImpl { + + @Override + protected LookupTableType getPredefinedValues(PrismProperty item, WrapperContext ctx) { + PrismObject prismObject = getParent(ctx); + if (!TaskType.class.equals(prismObject.getCompileTimeClass())) { + return super.getPredefinedValues(item, ctx); + } + + LookupTableType parentLookup = super.getPredefinedValues(item, ctx); + if (parentLookup != null) { + return parentLookup; + } + + TaskType task = (TaskType) prismObject.asObjectable(); + Collection assignmentTypes = task.getAssignment() + .stream() + .filter(WebComponentUtil::isArchetypeAssignment) + .collect(Collectors.toList()); + + Collection handlers; + if (assignmentTypes.isEmpty()) { + handlers = getTaskManager().getAllHandlerUris(true); + } else if (assignmentTypes.size() == 1) { + AssignmentType archetypeAssignment = assignmentTypes.iterator().next(); + handlers = getTaskManager().getHandlerUrisForArchetype(archetypeAssignment.getTargetRef().getOid(), true); + } else { + throw new UnsupportedOperationException("More than 1 archetype, this is not supported"); + } + LookupTableType lookupTableType = new LookupTableType(getPrismContext()); + + handlers.forEach(handler -> { + LookupTableRowType row = new LookupTableRowType(getPrismContext()); + row.setKey(handler); + handler = normalizeHandler(handler); + PolyStringType handlerLabel = new PolyStringType(handler); + PolyStringTranslationType translation = new PolyStringTranslationType(); + translation.setKey(handler); + handlerLabel.setTranslation(translation); + row.setLabel(handlerLabel); + lookupTableType.getRow().add(row); + }); + + return lookupTableType; + } + + private PrismObject getParent(WrapperContext ctx) { + return ctx.getObject(); + } + + private String normalizeHandler(String handler) { + handler = StringUtils.remove(handler, "-3"); + handler = StringUtils.removeStart(handler, "http://midpoint.evolveum.com/xml/ns/public/").replace("-", "/").replace("#", "/"); + String[] split = handler.split("/"); + handler = "TaskHandlerSelector." + StringUtils.join(split, "."); + return handler; + } + + + @Override + public int getOrder() { + return super.getOrder() - 10; + } + + @Override + public boolean match(ItemDefinition def) { + return TaskType.F_HANDLER_URI.equivalent(def.getItemName()); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/ContainerOfSystemConfigurationPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/ContainerOfSystemConfigurationPanel.java index a1712f3731c..a51aacf5170 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/ContainerOfSystemConfigurationPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/ContainerOfSystemConfigurationPanel.java @@ -1,104 +1,81 @@ -/* - * Copyright (c) 2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.gui.impl.page.admin.configuration.component; - -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.gui.impl.prism.ItemPanelSettingsBuilder; -import com.evolveum.midpoint.prism.path.ItemName; - -import org.apache.wicket.markup.html.panel.Panel; -import org.apache.wicket.model.IModel; - -import com.evolveum.midpoint.gui.api.component.BasePanel; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.prism.Containerable; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.prism.ItemVisibility; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.PcpAspectConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.PrimaryChangeProcessorConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; - -/** - * @author skublik - */ -public class ContainerOfSystemConfigurationPanel extends BasePanel> { - - private static final long serialVersionUID = 1L; - - private static final Trace LOGGER = TraceManager.getTrace(ContainerOfSystemConfigurationPanel.class); - - private static final String ID_CONTAINER = "container"; - private QName typeName = null; - - public ContainerOfSystemConfigurationPanel(String id, IModel> model, QName typeName) { - super(id, model); - this.typeName = typeName; - } - - @Override - protected void onInitialize() { - super.onInitialize(); - initLayout(); - } - - protected void initLayout() { - - try { - ItemPanelSettingsBuilder builder = new ItemPanelSettingsBuilder() - .visibilityHandler(wrapper -> getVisibity(wrapper.getPath())) - .showOnTopLevel(true); - Panel panel = getPageBase().initItemPanel(ID_CONTAINER, typeName, getModel(), builder.build()); -// getModelObject().setShowOnTopLevel(true); - add(panel); - } catch (SchemaException e) { - LOGGER.error("Cannot create panel for {}, {}", typeName, e.getMessage(), e); - getSession().error("Cannot create panel for " + typeName); // TODO opertion result? localization? - - } - - } - - protected ItemVisibility getVisibity(ItemPath itemPath) { - ItemName name = itemPath.firstToNameOrNull(); - if (name == null) { - return ItemVisibility.HIDDEN; - } - if (itemPath.firstToName().equals(SystemConfigurationType.F_WORKFLOW_CONFIGURATION)) { - if (itemPath.lastName().equals(WfConfigurationType.F_APPROVER_COMMENTS_FORMATTING)) { - return ItemVisibility.HIDDEN; - } - - if (itemPath.rest().equivalent(ItemPath.create(WfConfigurationType.F_PRIMARY_CHANGE_PROCESSOR, PrimaryChangeProcessorConfigurationType.F_ADD_ASSOCIATION_ASPECT, - PcpAspectConfigurationType.F_APPROVER_REF))) { - return ItemVisibility.AUTO; - } - - if (itemPath.rest().startsWithName(WfConfigurationType.F_PRIMARY_CHANGE_PROCESSOR) - && (itemPath.lastName().equals(PcpAspectConfigurationType.F_APPROVER_EXPRESSION) - || itemPath.lastName().equals(PcpAspectConfigurationType.F_APPROVER_REF) - || itemPath.lastName().equals(PcpAspectConfigurationType.F_AUTOMATICALLY_APPROVED) - || itemPath.lastName().equals(PcpAspectConfigurationType.F_APPLICABILITY_CONDITION))) { - return ItemVisibility.HIDDEN; - } - } - - if (itemPath.equivalent(ItemPath.create(SystemConfigurationType.F_ACCESS_CERTIFICATION, AccessCertificationConfigurationType.F_REVIEWER_COMMENTS_FORMATTING))) { - return ItemVisibility.HIDDEN; - } - - return ItemVisibility.AUTO; - } - - -} +/* + * Copyright (c) 2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.gui.impl.page.admin.configuration.component; + +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.gui.impl.prism.panel.ItemHeaderPanel; +import com.evolveum.midpoint.gui.impl.prism.panel.ItemPanelSettingsBuilder; +import com.evolveum.midpoint.gui.impl.prism.panel.SingleContainerPanel; +import com.evolveum.midpoint.prism.path.ItemName; + +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; + +import com.evolveum.midpoint.gui.api.component.BasePanel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.component.prism.ItemVisibility; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PcpAspectConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PrimaryChangeProcessorConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; + +/** + * @author skublik + */ +public class ContainerOfSystemConfigurationPanel extends SingleContainerPanel { + + private static final long serialVersionUID = 1L; + + private static final Trace LOGGER = TraceManager.getTrace(ContainerOfSystemConfigurationPanel.class); + + private static final String ID_CONTAINER = "container"; + + public ContainerOfSystemConfigurationPanel(String id, IModel> model, QName typeName) { + super(id, model, typeName); + } + + protected ItemVisibility getVisibity(ItemPath itemPath) { + ItemName name = itemPath.firstToNameOrNull(); + if (name == null) { + return ItemVisibility.HIDDEN; + } + if (itemPath.firstToName().equals(SystemConfigurationType.F_WORKFLOW_CONFIGURATION)) { + if (itemPath.lastName().equals(WfConfigurationType.F_APPROVER_COMMENTS_FORMATTING)) { + return ItemVisibility.HIDDEN; + } + + if (itemPath.rest().equivalent(ItemPath.create(WfConfigurationType.F_PRIMARY_CHANGE_PROCESSOR, PrimaryChangeProcessorConfigurationType.F_ADD_ASSOCIATION_ASPECT, + PcpAspectConfigurationType.F_APPROVER_REF))) { + return ItemVisibility.AUTO; + } + + if (itemPath.rest().startsWithName(WfConfigurationType.F_PRIMARY_CHANGE_PROCESSOR) + && (itemPath.lastName().equals(PcpAspectConfigurationType.F_APPROVER_EXPRESSION) + || itemPath.lastName().equals(PcpAspectConfigurationType.F_APPROVER_REF) + || itemPath.lastName().equals(PcpAspectConfigurationType.F_AUTOMATICALLY_APPROVED) + || itemPath.lastName().equals(PcpAspectConfigurationType.F_APPLICABILITY_CONDITION))) { + return ItemVisibility.HIDDEN; + } + } + + if (itemPath.equivalent(ItemPath.create(SystemConfigurationType.F_ACCESS_CERTIFICATION, AccessCertificationConfigurationType.F_REVIEWER_COMMENTS_FORMATTING))) { + return ItemVisibility.HIDDEN; + } + + return ItemVisibility.AUTO; + } + + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/GlobalPolicyRuleTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/GlobalPolicyRuleTabPanel.java index 599579d8ecc..b477dbc3b47 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/GlobalPolicyRuleTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/GlobalPolicyRuleTabPanel.java @@ -21,15 +21,15 @@ import com.evolveum.midpoint.gui.api.component.BasePanel; import com.evolveum.midpoint.gui.api.component.DisplayNamePanel; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.impl.component.MultivalueContainerDetailsPanel; import com.evolveum.midpoint.gui.impl.component.MultivalueContainerListPanelWithDetailsPanel; import com.evolveum.midpoint.gui.impl.component.data.column.AbstractItemWrapperColumn.ColumnType; import com.evolveum.midpoint.gui.impl.component.data.column.PrismContainerWrapperColumn; import com.evolveum.midpoint.gui.impl.component.data.column.PrismPropertyWrapperColumn; -import com.evolveum.midpoint.gui.impl.factory.ItemRealValueModel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.impl.factory.panel.ItemRealValueModel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.path.ItemPath; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/LoggingConfigurationTabPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/LoggingConfigurationTabPanel.html index 6f428b47dc1..637b986e86e 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/LoggingConfigurationTabPanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/LoggingConfigurationTabPanel.html @@ -8,7 +8,14 @@ -

+
+
+
+
+
+
+
+
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/LoggingConfigurationTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/LoggingConfigurationTabPanel.java index d71b3f0e9c4..72a9d03bec1 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/LoggingConfigurationTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/LoggingConfigurationTabPanel.java @@ -1,519 +1,517 @@ -/* - * Copyright (c) 2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.gui.impl.page.admin.configuration.component; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.gui.impl.prism.ItemPanelSettings; -import com.evolveum.midpoint.gui.impl.prism.ItemPanelSettingsBuilder; -import com.evolveum.midpoint.model.api.AssignmentObjectRelation; -import com.evolveum.midpoint.schema.constants.MidPointConstants; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import org.apache.commons.lang.StringUtils; -import org.apache.wicket.AttributeModifier; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.behavior.AttributeAppender; -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.WebMarkupContainer; -import org.apache.wicket.markup.html.basic.Label; -import org.apache.wicket.markup.html.list.ListItem; -import org.apache.wicket.markup.html.panel.Fragment; -import org.apache.wicket.markup.html.panel.Panel; -import org.apache.wicket.markup.repeater.Item; -import org.apache.wicket.model.IModel; -import org.apache.wicket.model.Model; -import org.apache.wicket.model.StringResourceModel; - -import com.evolveum.midpoint.gui.api.component.BasePanel; -import com.evolveum.midpoint.gui.api.component.DisplayNamePanel; -import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.impl.component.MultivalueContainerDetailsPanel; -import com.evolveum.midpoint.gui.impl.component.MultivalueContainerListPanel; -import com.evolveum.midpoint.gui.impl.component.MultivalueContainerListPanelWithDetailsPanel; -import com.evolveum.midpoint.gui.impl.component.data.column.AbstractItemWrapperColumn.ColumnType; -import com.evolveum.midpoint.gui.impl.component.data.column.PrismPropertyWrapperColumn; -import com.evolveum.midpoint.gui.impl.component.input.QNameIChoiceRenderer; -import com.evolveum.midpoint.gui.impl.factory.ItemRealValueModel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.prism.PrismContainerDefinition; -import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.util.QNameUtil; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.AjaxSubmitButton; -import com.evolveum.midpoint.web.component.data.column.CheckBoxHeaderColumn; -import com.evolveum.midpoint.web.component.data.column.IconColumn; -import com.evolveum.midpoint.web.component.data.column.InlineMenuButtonColumn; -import com.evolveum.midpoint.web.component.form.Form; -import com.evolveum.midpoint.web.component.input.DropDownChoicePanel; -import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItem; -import com.evolveum.midpoint.web.component.prism.ItemVisibility; -import com.evolveum.midpoint.web.component.search.SearchItemDefinition; -import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; -import com.evolveum.midpoint.web.model.PrismContainerWrapperModel; -import com.evolveum.midpoint.web.session.PageStorage; -import com.evolveum.midpoint.web.session.UserProfileStorage; -import com.evolveum.midpoint.web.session.UserProfileStorage.TableId; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AppenderConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AuditingConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ClassLoggerConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.DisplayType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.FileAppenderConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LoggingConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.SyslogAppenderConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; - -/** - * @author skublik - */ -public class LoggingConfigurationTabPanel extends BasePanel> { - - private static final long serialVersionUID = 1L; - - private static final Trace LOGGER = TraceManager.getTrace(LoggingConfigurationTabPanel.class); - - private static final String ID_LOGGING = "logging"; - private static final String ID_APPENDERS = "appenders"; - private static final String ID_LOGGERS = "loggers"; - private static final String ID_AUDITING = "audit"; - private static final String ID_NEW_ITEM_BUTTON = "newItemButton"; - private static final String ID_BUTTON_TOOLBAR_FRAGMENT = "buttonToolbarFragment"; - private static final String ID_APPENDERS_CHOICE = "appendersChoice"; - private static final String ID_CHOICE_APPENDER_TYPE_FORM = "choiceAppenderTypeForm"; - - - public LoggingConfigurationTabPanel(String id, IModel> model) { - super(id, model); - } - - @Override - protected void onInitialize() { - super.onInitialize(); - initLayout(); - } - - protected void initLayout() { - try { -// getModelObject().setShowOnTopLevel(true); - ItemPanelSettingsBuilder builder = new ItemPanelSettingsBuilder(); - builder.visibilityHandler(itemWrapper -> getLoggingVisibility(itemWrapper.getPath())).showOnTopLevel(true); - Panel loggingPanel = getPageBase().initItemPanel(ID_LOGGING, LoggingConfigurationType.COMPLEX_TYPE, getModel(), builder.build()); - add(loggingPanel); - } catch (SchemaException e) { - LOGGER.error("Cannot create panel for logging: {}", e.getMessage(), e); - getSession().error("Cannot create panle for logging"); - } - - TableId tableIdLoggers = UserProfileStorage.TableId.LOGGING_TAB_LOGGER_TABLE; - PageStorage pageStorageLoggers = getPageBase().getSessionStorage().getLoggingConfigurationTabLoggerTableStorage(); - - - PrismContainerWrapperModel loggerModel = PrismContainerWrapperModel.fromContainerWrapper(getModel(), LoggingConfigurationType.F_CLASS_LOGGER); - - MultivalueContainerListPanel loggersMultivalueContainerListPanel = - new MultivalueContainerListPanel(ID_LOGGERS, loggerModel, - tableIdLoggers, pageStorageLoggers) { - - private static final long serialVersionUID = 1L; - - @Override - protected List> postSearch( - List> items) { - return items; - } - - @Override - protected void newItemPerformed(AjaxRequestTarget target, AssignmentObjectRelation relation) { - PrismContainerValue newLogger = loggerModel.getObject().getItem().createNewValue(); - PrismContainerValueWrapper newLoggerWrapper = getLoggersMultivalueContainerListPanel().createNewItemContainerValueWrapper(newLogger, loggerModel.getObject(), target); - loggerEditPerformed(target, Model.of(newLoggerWrapper), null); - } - - @Override - protected void initPaging() { - initLoggerPaging(); - } - - @Override - protected boolean enableActionNewObject() { - return true; - } - - @Override - protected ObjectQuery createQuery() { - return null; - } - - @Override - protected List, String>> createColumns() { - return initLoggersBasicColumns(loggerModel); - } - - @Override - protected void itemPerformedForDefaultAction(AjaxRequestTarget target, - IModel> rowModel, - List> listItems) { - loggerEditPerformed(target, rowModel, listItems); - } - - @Override - protected List initSearchableItems( - PrismContainerDefinition containerDef) { - List defs = new ArrayList<>(); - - return defs; - } - }; - add(loggersMultivalueContainerListPanel); - - TableId tableIdAppenders = UserProfileStorage.TableId.LOGGING_TAB_APPENDER_TABLE; - PageStorage pageStorageAppenders = getPageBase().getSessionStorage().getLoggingConfigurationTabAppenderTableStorage(); - - - PrismContainerWrapperModel appenderModel = PrismContainerWrapperModel.fromContainerWrapper(getModel(), LoggingConfigurationType.F_APPENDER); - - MultivalueContainerListPanelWithDetailsPanel appendersMultivalueContainerListPanel = - new MultivalueContainerListPanelWithDetailsPanel(ID_APPENDERS, appenderModel, - tableIdAppenders, pageStorageAppenders) { - - private static final long serialVersionUID = 1L; - - @Override - protected List> postSearch( - List> items) { - return items; - } - - @Override - protected void newItemPerformed(AjaxRequestTarget target, AssignmentObjectRelation relation) { - newAppendersClickPerformed(target); - } - - @Override - protected void initPaging() { - initAppenderPaging(); - } - - @Override - protected boolean enableActionNewObject() { - return true; - } - - @Override - protected ObjectQuery createQuery() { - return null; - } - - @Override - protected List, String>> createColumns() { - return initAppendersBasicColumns(appenderModel); - } - - @Override - protected MultivalueContainerDetailsPanel getMultivalueContainerDetailsPanel( - ListItem> item) { - return LoggingConfigurationTabPanel.this.getAppendersMultivalueContainerDetailsPanel(item); - } - - @Override - protected List initSearchableItems( - PrismContainerDefinition containerDef) { - List defs = new ArrayList<>(); - - return defs; - } - - @Override - protected WebMarkupContainer initButtonToolbar(String contentAreaId) { - Fragment searchContainer = new Fragment(contentAreaId, ID_BUTTON_TOOLBAR_FRAGMENT, LoggingConfigurationTabPanel.this); - - Form appenderTypeForm = new Form(ID_CHOICE_APPENDER_TYPE_FORM); - searchContainer.add(appenderTypeForm); - - AjaxSubmitButton newObjectIcon = new AjaxSubmitButton(ID_NEW_ITEM_BUTTON, new Model<>("")) { - - private static final long serialVersionUID = 1L; - - @Override - protected void onSubmit(AjaxRequestTarget target) { - newItemPerformed(target, null); - } - }; - - newObjectIcon.add(new VisibleEnableBehaviour() { - private static final long serialVersionUID = 1L; - - @Override - public boolean isVisible() { - return enableActionNewObject(); - } - - @Override - public boolean isEnabled() { - return isNewObjectButtonEnabled(); - } - }); - newObjectIcon.add(AttributeModifier.append("class", createStyleClassModelForNewObjectIcon())); - appenderTypeForm.add(newObjectIcon); - List appendersChoicesList = new ArrayList(); - appendersChoicesList.add(FileAppenderConfigurationType.COMPLEX_TYPE); - appendersChoicesList.add(SyslogAppenderConfigurationType.COMPLEX_TYPE); - DropDownChoicePanel appenderChoise = new DropDownChoicePanel(ID_APPENDERS_CHOICE, new Model(FileAppenderConfigurationType.COMPLEX_TYPE), Model.of(appendersChoicesList), - new QNameIChoiceRenderer("LoggingConfigurationTabPanel." + ID_APPENDERS_CHOICE)); - appenderChoise.setOutputMarkupId(true); - appenderTypeForm.addOrReplace(appenderChoise); - return searchContainer; - } - - }; - add(appendersMultivalueContainerListPanel); - - IModel> auditModel = PrismContainerWrapperModel.fromContainerWrapper(getModel(), LoggingConfigurationType.F_AUDITING); - try { - Panel auditPanel = getPageBase().initItemPanel(ID_AUDITING, AuditingConfigurationType.COMPLEX_TYPE, auditModel, null); - add(auditPanel); - } catch (SchemaException e) { - LOGGER.error("Cannot create panel for auditing: {}", e.getMessage(), e); - getSession().error("Cannot create panel for auditing."); - } - setOutputMarkupId(true); - } - - private ItemVisibility getLoggingVisibility(ItemPath pathToCheck) { - if (ItemPath.create(SystemConfigurationType.F_LOGGING).equivalent(pathToCheck)) { - return ItemVisibility.AUTO; - } - - if (ItemPath.create(SystemConfigurationType.F_LOGGING, LoggingConfigurationType.F_ROOT_LOGGER_APPENDER).equivalent(pathToCheck)) { - return ItemVisibility.AUTO; - } - - if (ItemPath.create(SystemConfigurationType.F_LOGGING, LoggingConfigurationType.F_ROOT_LOGGER_LEVEL).equivalent(pathToCheck)) { - return ItemVisibility.AUTO; - } - - if (ItemPath.create(SystemConfigurationType.F_LOGGING, LoggingConfigurationType.F_DEBUG).equivalent(pathToCheck)) { - return ItemVisibility.AUTO; - } - - return ItemVisibility.HIDDEN; - } - - - private List, String>> initLoggersBasicColumns(IModel> loggersModel) { - List, String>> columns = new ArrayList<>(); - - columns.add(new CheckBoxHeaderColumn<>()); - columns.add(new IconColumn>(Model.of("")) { - - private static final long serialVersionUID = 1L; - - @Override - protected DisplayType getIconDisplayType(IModel> rowModel) { - return WebComponentUtil.createDisplayType(WebComponentUtil.createDefaultBlackIcon(SystemConfigurationType.COMPLEX_TYPE)); - - } - - }); - - columns.add(new PrismPropertyWrapperColumn(loggersModel, ClassLoggerConfigurationType.F_PACKAGE, ColumnType.VALUE, getPageBase()) { - - @Override - public String getCssClass() { - return " col-md-5 "; - } - - }); - columns.add(new PrismPropertyWrapperColumn<>(loggersModel, ClassLoggerConfigurationType.F_LEVEL, ColumnType.VALUE, getPageBase())); - columns.add(new PrismPropertyWrapperColumn<>(loggersModel, ClassLoggerConfigurationType.F_APPENDER, ColumnType.VALUE, getPageBase())); - - List menuActionsList = getLoggersMultivalueContainerListPanel().getDefaultMenuActions(); - columns.add(new InlineMenuButtonColumn(menuActionsList, getPageBase()) { - - @Override - public String getCssClass() { - return " col-md-1 "; - } - }); - - return columns; - } - - private void loggerEditPerformed(AjaxRequestTarget target, IModel> rowModel, - List> listItems) { - if(rowModel != null) { - PrismContainerValueWrapper logger = rowModel.getObject(); - logger.setSelected(true); - } else { - for(PrismContainerValueWrapper logger : listItems) { - logger.setSelected(true); - } - } - target.add(getLoggersMultivalueContainerListPanel()); - } - - - protected void newAppendersClickPerformed(AjaxRequestTarget target) { - MultivalueContainerListPanelWithDetailsPanel appenders - = (MultivalueContainerListPanelWithDetailsPanel) get(ID_APPENDERS); - DropDownChoicePanel appendersChoice = (DropDownChoicePanel) getAppendersMultivalueContainerListPanel().getItemTable().getFooterButtonToolbar().get(createComponentPath(ID_CHOICE_APPENDER_TYPE_FORM ,ID_APPENDERS_CHOICE)); - PrismContainerValue newObjectPolicy = null; - if(QNameUtil.match(appendersChoice.getModel().getObject(), FileAppenderConfigurationType.COMPLEX_TYPE)){ - newObjectPolicy = new FileAppenderConfigurationType().asPrismContainerValue(); - } else { - newObjectPolicy = new SyslogAppenderConfigurationType().asPrismContainerValue(); - } - newObjectPolicy.setParent(appenders.getModelObject().getItem()); - newObjectPolicy.setPrismContext(getPageBase().getPrismContext()); - - PrismContainerValueWrapper newAppenderContainerWrapper = getAppendersMultivalueContainerListPanel().createNewItemContainerValueWrapper(newObjectPolicy, appenders.getModelObject(), target); - getAppendersMultivalueContainerListPanel().itemDetailsPerformed(target, Arrays.asList(newAppenderContainerWrapper)); - } - - private MultivalueContainerDetailsPanel getAppendersMultivalueContainerDetailsPanel( - ListItem> item) { - MultivalueContainerDetailsPanel detailsPanel = - new MultivalueContainerDetailsPanel(MultivalueContainerListPanelWithDetailsPanel.ID_ITEM_DETAILS, item.getModel()) { - - private static final long serialVersionUID = 1L; - - @Override - protected DisplayNamePanel createDisplayNamePanel(String displayNamePanelId) { - IModel displayNameModel = new IModel() { - - private static final long serialVersionUID = 1L; - - @Override - public AppenderConfigurationType getObject() { - return item.getModelObject().getRealValue(); - } - }; - return new DisplayNamePanel(displayNamePanelId, displayNameModel); - } - }; - return detailsPanel; - } - - private boolean isFileAppender(IModel appender) { - if(appender == null || appender.getObject() == null) { - return false; - } - return (appender.getObject() instanceof FileAppenderConfigurationType); - } - - private boolean isSyslogAppender(IModel appender) { - if(appender == null || appender.getObject() == null) { - return false; - } - return (appender.getObject() instanceof SyslogAppenderConfigurationType); - } - - private String getInputCssClass() { - return "col-xs-10"; - } - - private Label createHeader(String id, String displayName) { - if (StringUtils.isEmpty(displayName)) { - displayName = "displayName.not.set"; - } - StringResourceModel headerLabelModel = createStringResource(displayName); - Label header = new Label(id, headerLabelModel); - header.add(AttributeAppender.prepend("class", "prism-title pull-left")); - return header; - } - - private MultivalueContainerListPanelWithDetailsPanel getAppendersMultivalueContainerListPanel(){ - return ((MultivalueContainerListPanelWithDetailsPanel)get(ID_APPENDERS)); - } - - private MultivalueContainerListPanel getLoggersMultivalueContainerListPanel(){ - return ((MultivalueContainerListPanel)get(ID_LOGGERS)); - } - - private void initAppenderPaging() { - getPageBase().getSessionStorage().getLoggingConfigurationTabAppenderTableStorage().setPaging( - getPrismContext().queryFactory().createPaging(0, (int) ((PageBase)getPage()).getItemsPerPage(UserProfileStorage.TableId.LOGGING_TAB_APPENDER_TABLE))); - } - - private void initLoggerPaging() { - getPageBase().getSessionStorage().getLoggingConfigurationTabLoggerTableStorage().setPaging( - getPrismContext().queryFactory().createPaging(0, (int) ((PageBase)getPage()).getItemsPerPage(UserProfileStorage.TableId.LOGGING_TAB_APPENDER_TABLE))); - } - - private List, String>> initAppendersBasicColumns(IModel> appenderModel) { - List, String>> columns = new ArrayList<>(); - - columns.add(new CheckBoxHeaderColumn<>()); - columns.add(new IconColumn>(Model.of("")) { - - private static final long serialVersionUID = 1L; - - @Override - protected DisplayType getIconDisplayType(IModel> rowModel) { - return WebComponentUtil.createDisplayType(WebComponentUtil.createDefaultBlackIcon(SystemConfigurationType.COMPLEX_TYPE)); - } - }); - - columns.add(new PrismPropertyWrapperColumn(appenderModel, AppenderConfigurationType.F_NAME, ColumnType.LINK, getPageBase()) { - - @Override - protected void onClick(AjaxRequestTarget target, IModel> rowModel) { - getAppendersMultivalueContainerListPanel().itemDetailsPerformed(target, rowModel); - } - - }); - - columns.add(new PrismPropertyWrapperColumn(appenderModel, AppenderConfigurationType.F_PATTERN, ColumnType.VALUE, getPageBase()) { - @Override - public String getCssClass() { - return " col-md-5 "; - } - }); - - columns.add(new AbstractColumn, String>(createStringResource("LoggingConfigurationTabPanel.appender.typeColumn")){ - private static final long serialVersionUID = 1L; - - @Override - public void populateItem(Item>> item, String componentId, - final IModel> rowModel) { - ItemRealValueModel appender = - new ItemRealValueModel<>(rowModel); - String type = ""; - if(appender != null && appender.getObject() instanceof FileAppenderConfigurationType) { - type = "File appender"; - } else if(appender != null && appender.getObject() instanceof SyslogAppenderConfigurationType) { - type = "Syslog appender"; - } - item.add(new Label(componentId, Model.of(type))); - } - }); - - List menuActionsList = getAppendersMultivalueContainerListPanel().getDefaultMenuActions(); - columns.add(new InlineMenuButtonColumn(menuActionsList, getPageBase()) { - @Override - public String getCssClass() { - return " col-md-1 "; - } - }); - - return columns; - } -} - +/* + * Copyright (c) 2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.gui.impl.page.admin.configuration.component; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.gui.impl.prism.panel.ItemPanelSettingsBuilder; +import com.evolveum.midpoint.model.api.AssignmentObjectRelation; + +import org.apache.commons.lang.StringUtils; +import org.apache.wicket.AttributeModifier; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.behavior.AttributeAppender; +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.WebMarkupContainer; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.panel.Fragment; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.markup.repeater.Item; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.StringResourceModel; + +import com.evolveum.midpoint.gui.api.component.BasePanel; +import com.evolveum.midpoint.gui.api.component.DisplayNamePanel; +import com.evolveum.midpoint.gui.api.page.PageBase; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.gui.impl.component.MultivalueContainerDetailsPanel; +import com.evolveum.midpoint.gui.impl.component.MultivalueContainerListPanel; +import com.evolveum.midpoint.gui.impl.component.MultivalueContainerListPanelWithDetailsPanel; +import com.evolveum.midpoint.gui.impl.component.data.column.AbstractItemWrapperColumn.ColumnType; +import com.evolveum.midpoint.gui.impl.component.data.column.PrismPropertyWrapperColumn; +import com.evolveum.midpoint.gui.impl.component.input.QNameIChoiceRenderer; +import com.evolveum.midpoint.gui.impl.factory.panel.ItemRealValueModel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.prism.PrismContainerDefinition; +import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.component.AjaxSubmitButton; +import com.evolveum.midpoint.web.component.data.column.CheckBoxHeaderColumn; +import com.evolveum.midpoint.web.component.data.column.IconColumn; +import com.evolveum.midpoint.web.component.data.column.InlineMenuButtonColumn; +import com.evolveum.midpoint.web.component.form.Form; +import com.evolveum.midpoint.web.component.input.DropDownChoicePanel; +import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItem; +import com.evolveum.midpoint.web.component.prism.ItemVisibility; +import com.evolveum.midpoint.web.component.search.SearchItemDefinition; +import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; +import com.evolveum.midpoint.web.model.PrismContainerWrapperModel; +import com.evolveum.midpoint.web.session.PageStorage; +import com.evolveum.midpoint.web.session.UserProfileStorage; +import com.evolveum.midpoint.web.session.UserProfileStorage.TableId; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AppenderConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AuditingConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ClassLoggerConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.DisplayType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.FileAppenderConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.LoggingConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SyslogAppenderConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; + +/** + * @author skublik + */ +public class LoggingConfigurationTabPanel extends BasePanel> { + + private static final long serialVersionUID = 1L; + + private static final Trace LOGGER = TraceManager.getTrace(LoggingConfigurationTabPanel.class); + + private static final String ID_LOGGING = "logging"; + private static final String ID_APPENDERS = "appenders"; + private static final String ID_LOGGERS = "loggers"; + private static final String ID_AUDITING = "audit"; + private static final String ID_NEW_ITEM_BUTTON = "newItemButton"; + private static final String ID_BUTTON_TOOLBAR_FRAGMENT = "buttonToolbarFragment"; + private static final String ID_APPENDERS_CHOICE = "appendersChoice"; + private static final String ID_CHOICE_APPENDER_TYPE_FORM = "choiceAppenderTypeForm"; + + + public LoggingConfigurationTabPanel(String id, IModel> model) { + super(id, model); + } + + @Override + protected void onInitialize() { + super.onInitialize(); + initLayout(); + } + + protected void initLayout() { + try { +// getModelObject().setShowOnTopLevel(true); + ItemPanelSettingsBuilder builder = new ItemPanelSettingsBuilder(); + builder.visibilityHandler(itemWrapper -> getLoggingVisibility(itemWrapper.getPath())); + Panel loggingPanel = getPageBase().initItemPanel(ID_LOGGING, LoggingConfigurationType.COMPLEX_TYPE, getModel(), builder.build()); + add(loggingPanel); + } catch (SchemaException e) { + LOGGER.error("Cannot create panel for logging: {}", e.getMessage(), e); + getSession().error("Cannot create panle for logging"); + } + + TableId tableIdLoggers = UserProfileStorage.TableId.LOGGING_TAB_LOGGER_TABLE; + PageStorage pageStorageLoggers = getPageBase().getSessionStorage().getLoggingConfigurationTabLoggerTableStorage(); + + + PrismContainerWrapperModel loggerModel = PrismContainerWrapperModel.fromContainerWrapper(getModel(), LoggingConfigurationType.F_CLASS_LOGGER); + + MultivalueContainerListPanel loggersMultivalueContainerListPanel = + new MultivalueContainerListPanel(ID_LOGGERS, loggerModel, + tableIdLoggers, pageStorageLoggers) { + + private static final long serialVersionUID = 1L; + + @Override + protected List> postSearch( + List> items) { + return items; + } + + @Override + protected void newItemPerformed(AjaxRequestTarget target, AssignmentObjectRelation relation) { + PrismContainerValue newLogger = loggerModel.getObject().getItem().createNewValue(); + PrismContainerValueWrapper newLoggerWrapper = getLoggersMultivalueContainerListPanel().createNewItemContainerValueWrapper(newLogger, loggerModel.getObject(), target); + loggerEditPerformed(target, Model.of(newLoggerWrapper), null); + } + + @Override + protected void initPaging() { + initLoggerPaging(); + } + + @Override + protected boolean enableActionNewObject() { + return true; + } + + @Override + protected ObjectQuery createQuery() { + return null; + } + + @Override + protected List, String>> createColumns() { + return initLoggersBasicColumns(loggerModel); + } + + @Override + protected void itemPerformedForDefaultAction(AjaxRequestTarget target, + IModel> rowModel, + List> listItems) { + loggerEditPerformed(target, rowModel, listItems); + } + + @Override + protected List initSearchableItems( + PrismContainerDefinition containerDef) { + List defs = new ArrayList<>(); + + return defs; + } + }; + add(loggersMultivalueContainerListPanel); + + TableId tableIdAppenders = UserProfileStorage.TableId.LOGGING_TAB_APPENDER_TABLE; + PageStorage pageStorageAppenders = getPageBase().getSessionStorage().getLoggingConfigurationTabAppenderTableStorage(); + + + PrismContainerWrapperModel appenderModel = PrismContainerWrapperModel.fromContainerWrapper(getModel(), LoggingConfigurationType.F_APPENDER); + + MultivalueContainerListPanelWithDetailsPanel appendersMultivalueContainerListPanel = + new MultivalueContainerListPanelWithDetailsPanel(ID_APPENDERS, appenderModel, + tableIdAppenders, pageStorageAppenders) { + + private static final long serialVersionUID = 1L; + + @Override + protected List> postSearch( + List> items) { + return items; + } + + @Override + protected void newItemPerformed(AjaxRequestTarget target, AssignmentObjectRelation relation) { + newAppendersClickPerformed(target); + } + + @Override + protected void initPaging() { + initAppenderPaging(); + } + + @Override + protected boolean enableActionNewObject() { + return true; + } + + @Override + protected ObjectQuery createQuery() { + return null; + } + + @Override + protected List, String>> createColumns() { + return initAppendersBasicColumns(appenderModel); + } + + @Override + protected MultivalueContainerDetailsPanel getMultivalueContainerDetailsPanel( + ListItem> item) { + return LoggingConfigurationTabPanel.this.getAppendersMultivalueContainerDetailsPanel(item); + } + + @Override + protected List initSearchableItems( + PrismContainerDefinition containerDef) { + List defs = new ArrayList<>(); + + return defs; + } + + @Override + protected WebMarkupContainer initButtonToolbar(String contentAreaId) { + Fragment searchContainer = new Fragment(contentAreaId, ID_BUTTON_TOOLBAR_FRAGMENT, LoggingConfigurationTabPanel.this); + + Form appenderTypeForm = new Form(ID_CHOICE_APPENDER_TYPE_FORM); + searchContainer.add(appenderTypeForm); + + AjaxSubmitButton newObjectIcon = new AjaxSubmitButton(ID_NEW_ITEM_BUTTON, new Model<>("")) { + + private static final long serialVersionUID = 1L; + + @Override + protected void onSubmit(AjaxRequestTarget target) { + newItemPerformed(target, null); + } + }; + + newObjectIcon.add(new VisibleEnableBehaviour() { + private static final long serialVersionUID = 1L; + + @Override + public boolean isVisible() { + return enableActionNewObject(); + } + + @Override + public boolean isEnabled() { + return isNewObjectButtonEnabled(); + } + }); + newObjectIcon.add(AttributeModifier.append("class", createStyleClassModelForNewObjectIcon())); + appenderTypeForm.add(newObjectIcon); + List appendersChoicesList = new ArrayList(); + appendersChoicesList.add(FileAppenderConfigurationType.COMPLEX_TYPE); + appendersChoicesList.add(SyslogAppenderConfigurationType.COMPLEX_TYPE); + DropDownChoicePanel appenderChoise = new DropDownChoicePanel(ID_APPENDERS_CHOICE, new Model(FileAppenderConfigurationType.COMPLEX_TYPE), Model.of(appendersChoicesList), + new QNameIChoiceRenderer("LoggingConfigurationTabPanel." + ID_APPENDERS_CHOICE)); + appenderChoise.setOutputMarkupId(true); + appenderTypeForm.addOrReplace(appenderChoise); + return searchContainer; + } + + }; + add(appendersMultivalueContainerListPanel); + + IModel> auditModel = PrismContainerWrapperModel.fromContainerWrapper(getModel(), LoggingConfigurationType.F_AUDITING); + try { + Panel auditPanel = getPageBase().initItemPanel(ID_AUDITING, AuditingConfigurationType.COMPLEX_TYPE, auditModel, new ItemPanelSettingsBuilder().build()); + add(auditPanel); + } catch (SchemaException e) { + LOGGER.error("Cannot create panel for auditing: {}", e.getMessage(), e); + getSession().error("Cannot create panel for auditing."); + } + setOutputMarkupId(true); + } + + private ItemVisibility getLoggingVisibility(ItemPath pathToCheck) { + if (ItemPath.create(SystemConfigurationType.F_LOGGING).equivalent(pathToCheck)) { + return ItemVisibility.AUTO; + } + + if (ItemPath.create(SystemConfigurationType.F_LOGGING, LoggingConfigurationType.F_ROOT_LOGGER_APPENDER).equivalent(pathToCheck)) { + return ItemVisibility.AUTO; + } + + if (ItemPath.create(SystemConfigurationType.F_LOGGING, LoggingConfigurationType.F_ROOT_LOGGER_LEVEL).equivalent(pathToCheck)) { + return ItemVisibility.AUTO; + } + + if (ItemPath.create(SystemConfigurationType.F_LOGGING, LoggingConfigurationType.F_DEBUG).equivalent(pathToCheck)) { + return ItemVisibility.AUTO; + } + + return ItemVisibility.HIDDEN; + } + + + private List, String>> initLoggersBasicColumns(IModel> loggersModel) { + List, String>> columns = new ArrayList<>(); + + columns.add(new CheckBoxHeaderColumn<>()); + columns.add(new IconColumn>(Model.of("")) { + + private static final long serialVersionUID = 1L; + + @Override + protected DisplayType getIconDisplayType(IModel> rowModel) { + return WebComponentUtil.createDisplayType(WebComponentUtil.createDefaultBlackIcon(SystemConfigurationType.COMPLEX_TYPE)); + + } + + }); + + columns.add(new PrismPropertyWrapperColumn(loggersModel, ClassLoggerConfigurationType.F_PACKAGE, ColumnType.VALUE, getPageBase()) { + + @Override + public String getCssClass() { + return " col-md-5 "; + } + + }); + columns.add(new PrismPropertyWrapperColumn<>(loggersModel, ClassLoggerConfigurationType.F_LEVEL, ColumnType.VALUE, getPageBase())); + columns.add(new PrismPropertyWrapperColumn<>(loggersModel, ClassLoggerConfigurationType.F_APPENDER, ColumnType.VALUE, getPageBase())); + + List menuActionsList = getLoggersMultivalueContainerListPanel().getDefaultMenuActions(); + columns.add(new InlineMenuButtonColumn(menuActionsList, getPageBase()) { + + @Override + public String getCssClass() { + return " col-md-1 "; + } + }); + + return columns; + } + + private void loggerEditPerformed(AjaxRequestTarget target, IModel> rowModel, + List> listItems) { + if(rowModel != null) { + PrismContainerValueWrapper logger = rowModel.getObject(); + logger.setSelected(true); + } else { + for(PrismContainerValueWrapper logger : listItems) { + logger.setSelected(true); + } + } + target.add(getLoggersMultivalueContainerListPanel()); + } + + + protected void newAppendersClickPerformed(AjaxRequestTarget target) { + MultivalueContainerListPanelWithDetailsPanel appenders + = (MultivalueContainerListPanelWithDetailsPanel) get(ID_APPENDERS); + DropDownChoicePanel appendersChoice = (DropDownChoicePanel) getAppendersMultivalueContainerListPanel().getItemTable().getFooterButtonToolbar().get(createComponentPath(ID_CHOICE_APPENDER_TYPE_FORM ,ID_APPENDERS_CHOICE)); + PrismContainerValue newObjectPolicy = null; + if(QNameUtil.match(appendersChoice.getModel().getObject(), FileAppenderConfigurationType.COMPLEX_TYPE)){ + newObjectPolicy = new FileAppenderConfigurationType().asPrismContainerValue(); + } else { + newObjectPolicy = new SyslogAppenderConfigurationType().asPrismContainerValue(); + } + newObjectPolicy.setParent(appenders.getModelObject().getItem()); + newObjectPolicy.setPrismContext(getPageBase().getPrismContext()); + + PrismContainerValueWrapper newAppenderContainerWrapper = getAppendersMultivalueContainerListPanel().createNewItemContainerValueWrapper(newObjectPolicy, appenders.getModelObject(), target); + getAppendersMultivalueContainerListPanel().itemDetailsPerformed(target, Arrays.asList(newAppenderContainerWrapper)); + } + + private MultivalueContainerDetailsPanel getAppendersMultivalueContainerDetailsPanel( + ListItem> item) { + MultivalueContainerDetailsPanel detailsPanel = + new MultivalueContainerDetailsPanel(MultivalueContainerListPanelWithDetailsPanel.ID_ITEM_DETAILS, item.getModel()) { + + private static final long serialVersionUID = 1L; + + @Override + protected DisplayNamePanel createDisplayNamePanel(String displayNamePanelId) { + IModel displayNameModel = new IModel() { + + private static final long serialVersionUID = 1L; + + @Override + public AppenderConfigurationType getObject() { + return item.getModelObject().getRealValue(); + } + }; + return new DisplayNamePanel(displayNamePanelId, displayNameModel); + } + }; + return detailsPanel; + } + + private boolean isFileAppender(IModel appender) { + if(appender == null || appender.getObject() == null) { + return false; + } + return (appender.getObject() instanceof FileAppenderConfigurationType); + } + + private boolean isSyslogAppender(IModel appender) { + if(appender == null || appender.getObject() == null) { + return false; + } + return (appender.getObject() instanceof SyslogAppenderConfigurationType); + } + + private String getInputCssClass() { + return "col-xs-10"; + } + + private Label createHeader(String id, String displayName) { + if (StringUtils.isEmpty(displayName)) { + displayName = "displayName.not.set"; + } + StringResourceModel headerLabelModel = createStringResource(displayName); + Label header = new Label(id, headerLabelModel); + header.add(AttributeAppender.prepend("class", "prism-title pull-left")); + return header; + } + + private MultivalueContainerListPanelWithDetailsPanel getAppendersMultivalueContainerListPanel(){ + return ((MultivalueContainerListPanelWithDetailsPanel)get(ID_APPENDERS)); + } + + private MultivalueContainerListPanel getLoggersMultivalueContainerListPanel(){ + return ((MultivalueContainerListPanel)get(ID_LOGGERS)); + } + + private void initAppenderPaging() { + getPageBase().getSessionStorage().getLoggingConfigurationTabAppenderTableStorage().setPaging( + getPrismContext().queryFactory().createPaging(0, (int) ((PageBase)getPage()).getItemsPerPage(UserProfileStorage.TableId.LOGGING_TAB_APPENDER_TABLE))); + } + + private void initLoggerPaging() { + getPageBase().getSessionStorage().getLoggingConfigurationTabLoggerTableStorage().setPaging( + getPrismContext().queryFactory().createPaging(0, (int) ((PageBase)getPage()).getItemsPerPage(UserProfileStorage.TableId.LOGGING_TAB_APPENDER_TABLE))); + } + + private List, String>> initAppendersBasicColumns(IModel> appenderModel) { + List, String>> columns = new ArrayList<>(); + + columns.add(new CheckBoxHeaderColumn<>()); + columns.add(new IconColumn>(Model.of("")) { + + private static final long serialVersionUID = 1L; + + @Override + protected DisplayType getIconDisplayType(IModel> rowModel) { + return WebComponentUtil.createDisplayType(WebComponentUtil.createDefaultBlackIcon(SystemConfigurationType.COMPLEX_TYPE)); + } + }); + + columns.add(new PrismPropertyWrapperColumn(appenderModel, AppenderConfigurationType.F_NAME, ColumnType.LINK, getPageBase()) { + + @Override + protected void onClick(AjaxRequestTarget target, IModel> rowModel) { + getAppendersMultivalueContainerListPanel().itemDetailsPerformed(target, rowModel); + } + + }); + + columns.add(new PrismPropertyWrapperColumn(appenderModel, AppenderConfigurationType.F_PATTERN, ColumnType.VALUE, getPageBase()) { + @Override + public String getCssClass() { + return " col-md-5 "; + } + }); + + columns.add(new AbstractColumn, String>(createStringResource("LoggingConfigurationTabPanel.appender.typeColumn")){ + private static final long serialVersionUID = 1L; + + @Override + public void populateItem(Item>> item, String componentId, + final IModel> rowModel) { + ItemRealValueModel appender = + new ItemRealValueModel<>(rowModel); + String type = ""; + if(appender != null && appender.getObject() instanceof FileAppenderConfigurationType) { + type = "File appender"; + } else if(appender != null && appender.getObject() instanceof SyslogAppenderConfigurationType) { + type = "Syslog appender"; + } + item.add(new Label(componentId, Model.of(type))); + } + }); + + List menuActionsList = getAppendersMultivalueContainerListPanel().getDefaultMenuActions(); + columns.add(new InlineMenuButtonColumn(menuActionsList, getPageBase()) { + @Override + public String getCssClass() { + return " col-md-1 "; + } + }); + + return columns; + } +} + diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/NotificationConfigTabPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/NotificationConfigTabPanel.html index 470fb943399..416b76718f6 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/NotificationConfigTabPanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/NotificationConfigTabPanel.html @@ -8,26 +8,30 @@ -
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ +
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/NotificationConfigTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/NotificationConfigTabPanel.java index 706659e0c1d..be016505673 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/NotificationConfigTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/NotificationConfigTabPanel.java @@ -35,15 +35,15 @@ import com.evolveum.midpoint.gui.api.GuiStyleConstants; import com.evolveum.midpoint.gui.api.component.BasePanel; import com.evolveum.midpoint.gui.api.component.password.PasswordPanel; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.api.util.WebPrismUtil; import com.evolveum.midpoint.gui.impl.component.data.column.EditableColumn; import com.evolveum.midpoint.gui.impl.component.form.TriStateFormGroup; -import com.evolveum.midpoint.gui.impl.factory.ItemRealValueModel; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyHeaderPanel; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; +import com.evolveum.midpoint.gui.impl.factory.panel.ItemRealValueModel; +import com.evolveum.midpoint.gui.impl.prism.panel.PrismPropertyHeaderPanel; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismPropertyValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; import com.evolveum.midpoint.prism.PrismPropertyValue; import com.evolveum.midpoint.prism.query.ObjectPaging; import com.evolveum.midpoint.prism.query.ObjectQuery; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/ObjectPolicyConfigurationTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/ObjectPolicyConfigurationTabPanel.java index 63d2155a4dd..431d19e9f0d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/ObjectPolicyConfigurationTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/ObjectPolicyConfigurationTabPanel.java @@ -14,8 +14,8 @@ import javax.xml.namespace.QName; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.impl.prism.ItemMandatoryHandler; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemMandatoryHandler; import com.evolveum.midpoint.model.api.AssignmentObjectRelation; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; @@ -29,15 +29,15 @@ import com.evolveum.midpoint.gui.api.component.BasePanel; import com.evolveum.midpoint.gui.api.component.DisplayNamePanel; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; import com.evolveum.midpoint.gui.impl.component.MultivalueContainerDetailsPanel; import com.evolveum.midpoint.gui.impl.component.MultivalueContainerListPanelWithDetailsPanel; import com.evolveum.midpoint.gui.impl.component.data.column.AbstractItemWrapperColumn.ColumnType; import com.evolveum.midpoint.gui.impl.component.data.column.PrismContainerWrapperColumn; import com.evolveum.midpoint.gui.impl.component.data.column.PrismPropertyWrapperColumn; import com.evolveum.midpoint.gui.impl.component.data.column.PrismReferenceWrapperColumn; -import com.evolveum.midpoint.gui.impl.factory.ItemRealValueModel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.impl.factory.panel.ItemRealValueModel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.query.ObjectQuery; @@ -66,7 +66,6 @@ public class ObjectPolicyConfigurationTabPanel extends B public ObjectPolicyConfigurationTabPanel(String id, IModel> model) { super(id, model); -// getModel().getObject().getValues().clear(); } @Override @@ -180,7 +179,7 @@ protected ItemMandatoryHandler getMandatoryHandler() { return detailsPanel; } - private boolean getMandatoryOverrideFor(ItemWrapper itemWrapper) { + private boolean getMandatoryOverrideFor(ItemWrapper itemWrapper) { ItemPath conflictResolutionPath = ItemPath.create(SystemConfigurationType.F_DEFAULT_OBJECT_POLICY_CONFIGURATION, ObjectPolicyConfigurationType.F_CONFLICT_RESOLUTION, ConflictResolutionType.F_ACTION); if (conflictResolutionPath.equivalent(itemWrapper.getPath().namedSegmentsOnly())) { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/ProfilingConfigurationTabPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/ProfilingConfigurationTabPanel.html index 4ee0802b5c3..9539003359a 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/ProfilingConfigurationTabPanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/ProfilingConfigurationTabPanel.html @@ -18,8 +18,12 @@

-
-
+
+
+
+
+
+
- - - - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismObjectHeaderPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismObjectHeaderPanel.java deleted file mode 100644 index 7e55bd51334..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismObjectHeaderPanel.java +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.prism; - -/** - * @author katka - * - */ -public class PrismObjectHeaderPanel { - -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyHeaderPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyHeaderPanel.html deleted file mode 100644 index fda983f842e..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyHeaderPanel.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - -
- - - * - - - - - - - - - -
- -
- diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyPanel.html deleted file mode 100644 index 240d0e0aac8..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyPanel.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - -
-
- - - diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyPanel.java deleted file mode 100644 index 2b9238bd82b..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyPanel.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.gui.impl.prism; - -import com.evolveum.midpoint.gui.api.Validatable; -import com.evolveum.midpoint.gui.api.factory.GuiComponentFactory; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.impl.error.ErrorPanel; -import com.evolveum.midpoint.gui.impl.factory.PrismPropertyPanelContext; -import com.evolveum.midpoint.prism.Containerable; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismValue; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.LoggingUtils; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.message.FeedbackAlerts; -import com.evolveum.midpoint.web.component.prism.InputPanel; -import com.evolveum.midpoint.web.component.util.EnableBehaviour; -import com.evolveum.midpoint.web.util.ExpressionValidator; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import org.apache.wicket.AttributeModifier; -import org.apache.wicket.Component; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; -import org.apache.wicket.feedback.ComponentFeedbackMessageFilter; -import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.markup.html.basic.Label; -import org.apache.wicket.markup.html.form.Form; -import org.apache.wicket.markup.html.form.FormComponent; -import org.apache.wicket.markup.html.form.TextField; -import org.apache.wicket.markup.html.list.ListItem; -import org.apache.wicket.markup.html.panel.Panel; -import org.apache.wicket.model.IModel; -import org.apache.wicket.model.LambdaModel; - -import java.util.List; - -/** - * @author katkav - */ -public class PrismPropertyPanel extends ItemPanel, PrismPropertyWrapper> { - - private static final long serialVersionUID = 1L; - private static final Trace LOGGER = TraceManager.getTrace(PrismPropertyPanel.class); - - private static final String ID_HEADER = "header"; - - private static final String ID_FEEDBACK = "feedback"; - private static final String ID_VALUE_CONTAINER = "valueContainer"; - - private static final String ID_FORM = "form"; - private static final String ID_INPUT = "input"; - - - /** - * @param id - * @param model - */ - public PrismPropertyPanel(String id, IModel> model, ItemPanelSettings settings) { - super(id, model, settings); - } - - - @Override - protected Panel createHeaderPanel() { - return new PrismPropertyHeaderPanel<>(ID_HEADER, getModel()); - } - - - @Override - protected Component createValuePanel(ListItem> item, GuiComponentFactory factory, - ItemVisibilityHandler visibilityHandler, ItemEditabilityHandler editabilityHandler) { - - return createInputPanel(item, factory); - - - - } - - private WebMarkupContainer createInputPanel(ListItem> item, GuiComponentFactory factory) { - - WebMarkupContainer valueContainer = new WebMarkupContainer(ID_VALUE_CONTAINER); - valueContainer.setOutputMarkupId(true); - item.add(valueContainer); - // feedback - FeedbackAlerts feedback = new FeedbackAlerts(ID_FEEDBACK); - feedback.setOutputMarkupId(true); - item.add(feedback); - - PrismPropertyWrapper modelObject = getModelObject(); - - LOGGER.trace("create input component for: {}", modelObject.debugDump()); - - Panel component = null; - - Form form = new Form<>(ID_FORM); - valueContainer.add(form); - - if (factory == null) { - if (getPageBase().getApplication().usesDevelopmentConfig()) { - form.add(new ErrorPanel(ID_INPUT, createStringResource("Cannot create component for: " + modelObject.getItem()))); - } else { - Label noComponent = new Label(ID_INPUT); - noComponent.setVisible(false); - form.add(noComponent); - } - return valueContainer; - } - - if (factory != null) { - - PrismPropertyPanelContext panelCtx = new PrismPropertyPanelContext(getModel()); - panelCtx.setForm(form); - panelCtx.setRealValueModel(item.getModel()); - panelCtx.setComponentId(ID_INPUT); - panelCtx.setParentComponent(this); - - try { - component = factory.createPanel(panelCtx); - form.add(component); - } catch (Throwable e) { - LoggingUtils.logUnexpectedException(LOGGER, "Cannot create panel", e); - getSession().error("Cannot create panel"); - throw new RuntimeException(e); - } - } - - if (component instanceof Validatable) { - Validatable inputPanel = (Validatable) component; - // adding valid from/to date range validator, if necessary - ExpressionValidator expressionValidator = new ExpressionValidator( - LambdaModel.of(modelObject::getFormComponentValidator), getPageBase()) { - - private static final long serialVersionUID = 1L; - - @Override - protected O getObjectType() { - return getObject(); - } - }; - inputPanel.getValidatableComponent().add(expressionValidator); - - inputPanel.getValidatableComponent().add(new AjaxFormComponentUpdatingBehavior("change") { - - private static final long serialVersionUID = 1L; - - @Override - protected void onUpdate(AjaxRequestTarget target) { - target.add(getPageBase().getFeedbackPanel()); - target.add(feedback); - } - - @Override - protected void onError(AjaxRequestTarget target, RuntimeException e) { - target.add(getPageBase().getFeedbackPanel()); - target.add(feedback); - } - - }); - feedback.setFilter(new ComponentFeedbackMessageFilter(inputPanel.getValidatableComponent())); - } else { - feedback.setFilter(new ComponentFeedbackMessageFilter(component)); - } - - if (component instanceof InputPanel) { - InputPanel inputPanel = (InputPanel) component; - - final List formComponents = inputPanel.getFormComponents(); - for (FormComponent formComponent : formComponents) { - IModel label = LambdaModel.of(modelObject::getDisplayName); - formComponent.setLabel(label); - formComponent.setRequired(getMandatoryHandler() == null ? modelObject.isMandatory() : getMandatoryHandler().isMandatory(modelObject)); - - if (formComponent instanceof TextField) { - formComponent.add(new AttributeModifier("size", "42")); - } - formComponent.add(new AjaxFormComponentUpdatingBehavior("change") { - - private static final long serialVersionUID = 1L; - - @Override - protected void onUpdate(AjaxRequestTarget target) { - target.add(getPageBase().getFeedbackPanel()); - target.add(feedback); - } - - @Override - protected void onError(AjaxRequestTarget target, RuntimeException e) { - target.add(getPageBase().getFeedbackPanel()); - target.add(feedback); - } - - }); - formComponent.add(new EnableBehaviour(() -> getEditabilityHandler() == null || - getEditabilityHandler().isEditable(getModelObject()))); - } - - - } - if (component == null) { - WebMarkupContainer cont = new WebMarkupContainer(ID_INPUT); - cont.setOutputMarkupId(true); - return cont; - } - return valueContainer; - - } - - private , O extends ObjectType, C extends Containerable> O getObject() { - - OW objectWrapper = getModelObject().findObjectWrapper(); - if (objectWrapper == null) { - return null; - } - - try { - PrismObject objectNew = objectWrapper.getObjectApplyDelta(); - return objectNew.asObjectable(); - } catch (SchemaException e) { - LOGGER.error("Cannot apply deltas to object for validation: {}", e.getMessage(), e); - return null; - } - } - - @Override - protected PV createNewValue(PrismPropertyWrapper itemWrapper) { - return (PV) getPrismContext().itemFactory().createPropertyValue(); - } -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismReferenceHeaderPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismReferenceHeaderPanel.html deleted file mode 100644 index dae485ddfde..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismReferenceHeaderPanel.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - -
- - - * - - - - - - - - -
-
- diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismReferencePanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismReferencePanel.html deleted file mode 100644 index d0d186d181e..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismReferencePanel.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - -
-
-
-
- -
- - - - - -
-
-
- -
-
- - diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismReferencePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismReferencePanel.java deleted file mode 100644 index a1ff5b5eb33..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismReferencePanel.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.prism; - -import java.util.Arrays; -import java.util.List; - -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.prism.PrismValue; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import org.apache.commons.collections.CollectionUtils; -import org.apache.wicket.Component; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.feedback.ComponentFeedbackMessageFilter; -import org.apache.wicket.markup.html.list.ListItem; -import org.apache.wicket.markup.html.panel.Panel; -import org.apache.wicket.model.IModel; -import org.apache.wicket.model.LambdaModel; -import org.apache.wicket.validation.IValidatable; - -import com.evolveum.midpoint.gui.api.factory.GuiComponentFactory; -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.api.util.WebPrismUtil; -import com.evolveum.midpoint.gui.impl.factory.ItemRealValueModel; -import com.evolveum.midpoint.gui.impl.factory.PrismReferencePanelContext; -import com.evolveum.midpoint.prism.PrismReferenceValue; -import com.evolveum.midpoint.prism.Referencable; -import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.form.ValueChoosePanel; -import com.evolveum.midpoint.web.component.message.FeedbackAlerts; -import com.evolveum.midpoint.web.util.ExpressionValidator; - -/** - * @author katka - * - */ -public class PrismReferencePanel extends ItemPanel, PrismReferenceWrapper>{ - - private static final long serialVersionUID = 1L; - private static final Trace LOGGER = TraceManager.getTrace(PrismReferencePanel.class); - - private static final String ID_HEADER = "header"; - private static final String ID_VALUE = "value"; - private static final String ID_FEEDBACK = "feedback"; - - public PrismReferencePanel(String id, IModel> model, ItemPanelSettings settings) { - super(id, model, settings); - } - - @Override - protected Panel createHeaderPanel() { - return new PrismReferenceHeaderPanel(ID_HEADER, getModel()); - } - - @Override - protected Component createValuePanel(ListItem> item, GuiComponentFactory componentFactory, - ItemVisibilityHandler visibilityHandler, ItemEditabilityHandler editabilityHandler) { - FeedbackAlerts feedback = new FeedbackAlerts(ID_FEEDBACK); - feedback.setOutputMarkupId(true); - item.add(feedback); - - if (componentFactory != null) { - PrismReferencePanelContext panelCtx = new PrismReferencePanelContext<>(getModel()); - panelCtx.setComponentId(ID_VALUE); - panelCtx.setParentComponent(this); - panelCtx.setRealValueModel((IModel)item.getModel()); - - Panel panel = componentFactory.createPanel(panelCtx); - item.add(panel); - return panel; - } else { - ValueChoosePanel panel = new ValueChoosePanel(ID_VALUE, new ItemRealValueModel<>(item.getModel())) { - - private static final long serialVersionUID = 1L; - - @Override - protected ObjectFilter createCustomFilter() { - return PrismReferencePanel.this.getModelObject().getFilter(); - } - - @Override - protected boolean isEditButtonEnabled() { -// if (getModel() == null) { -// return true; -// } -// -// //TODO only is association -// return getModelObject() == null; - if (item.getModel() == null || item.getModelObject() == null) { - return true; - } - return item.getModelObject().isEditEnabled(); - - } - - @Override - protected void choosePerformed(AjaxRequestTarget target, O object) { - super.choosePerformed(target, object); - getBaseFormComponent().validate(); - target.add(getPageBase().getFeedbackPanel()); - target.add(feedback); - } - - @Override - public List getSupportedTypes() { - List targetTypeList = PrismReferencePanel.this.getModelObject().getTargetTypes(); - if (targetTypeList == null || WebComponentUtil.isAllNulls(targetTypeList)) { - return Arrays.asList(ObjectType.COMPLEX_TYPE); - } - return targetTypeList; - } - - @Override - protected Class getDefaultType(List supportedTypes) { - if (AbstractRoleType.COMPLEX_TYPE.equals(PrismReferencePanel.this.getModelObject().getTargetTypeName())) { - return (Class) RoleType.class; - } else { - return super.getDefaultType(supportedTypes); - } - } - - }; - - ExpressionValidator expressionValidator = new ExpressionValidator( - LambdaModel.of(getModel().getObject()::getFormComponentValidator), getPageBase()) { - - private static final long serialVersionUID = 1L; - - @Override - protected Object getValueToValidate(IValidatable validatable) { - return item.getModelObject().getRealValue(); - } - }; - panel.getBaseFormComponent().add(expressionValidator); - feedback.setFilter(new ComponentFeedbackMessageFilter(panel)); - item.add(panel); - - return panel; - } - } - - protected void addValue(AjaxRequestTarget target) { - PrismReferenceWrapper referenceWrapper = getModel().getObject(); - PrismReferenceValue newValue = getPrismContext().itemFactory().createReferenceValue(); - - WebPrismUtil.createNewValueWrapper(referenceWrapper, newValue, getPageBase(), target); - - target.add(PrismReferencePanel.this); - } - - @Override - public boolean isEnabled() { - if (getEditabilityHandler() != null && !getEditabilityHandler().isEditable(getModelObject())) { - return false; - } - return !getModelObject().isReadOnly() || isLink(getModelObject()); - } - - private boolean isLink(PrismReferenceWrapper iw){ - boolean isLink = false; - if (CollectionUtils.isNotEmpty(iw.getValues()) && iw.getValues().size() == 1) { - isLink = iw.getValues().get(0).isLink(); - } - return isLink; - } - - @Override - protected PV createNewValue(PrismReferenceWrapper itemWrapper) { - return (PV) getPrismContext().itemFactory().createReferenceValue(); - } -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ShadowAssociationReferenceWrapperImpl.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ShadowAssociationReferenceWrapperImpl.java deleted file mode 100644 index ae508123fc5..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ShadowAssociationReferenceWrapperImpl.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.prism; - -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.prism.PrismReference; -import com.evolveum.midpoint.prism.Referencable; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; - -/** - * @author skublik - * - */ -public class ShadowAssociationReferenceWrapperImpl extends PrismReferenceWrapperImpl { - - private static final long serialVersionUID = 1L; - - private String displayName; - - public ShadowAssociationReferenceWrapperImpl(PrismContainerValueWrapper parent, PrismReference item, - ItemStatus status) { - super(parent, item, status); - } - - - @Override - public String getDisplayName() { - if(displayName != null) { - return displayName; - } - return super.getDisplayName(); - } - - @Override - public QName getTargetTypeName() { - return ShadowType.COMPLEX_TYPE; - } - - public void setDisplayName(String displayName) { - this.displayName = displayName; - } -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ShadowPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ShadowPanel.html deleted file mode 100644 index 4aa4f0747ec..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ShadowPanel.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - -
-
-
-
- - diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/PrismContainerHeaderPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/PrismContainerHeaderPanel.java deleted file mode 100644 index 760966f4f7e..00000000000 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/PrismContainerHeaderPanel.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.prism.component; - -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.ajax.markup.html.AjaxLink; -import org.apache.wicket.model.IModel; - -import com.evolveum.midpoint.gui.api.component.BasePanel; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.prism.Containerable; -import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; - -/** - * @author katka - * - */ -public class PrismContainerHeaderPanel extends BasePanel> { //ItemHeaderPanel>{ - - private static final long serialVersionUID = 1L; - - private static final String ID_ADD_BUTTON = "addButton"; - private static final String ID_EXPAND_COLLAPSE_FRAGMENT = "expandCollapseFragment"; - private static final String ID_EXPAND_COLLAPSE_BUTTON = "expandCollapseButton"; - - public PrismContainerHeaderPanel(String id, IModel> model) { - super(id, model); - - } - - @Override - protected void onInitialize() { - super.onInitialize(); - initLayout(); - } - - private void initLayout() { - setOutputMarkupId(true); - - initButtons(); -// initHeaderLabel(); - } - -// @Override - protected void initButtons() { - - add(new VisibleEnableBehaviour() { - - private static final long serialVersionUID = 1L; - - @Override - public boolean isVisible() { - return isContainerMultivalue(); - } - }); - - AjaxLink addButton = new AjaxLink(ID_ADD_BUTTON) { - private static final long serialVersionUID = 1L; - - @Override - public void onClick(AjaxRequestTarget target) { - addValue(target); - } - }; - addButton.add(new VisibleEnableBehaviour() { - - private static final long serialVersionUID = 1L; - - @Override - public boolean isVisible() { - return isAddButtonVisible(); - } - }); - - add(addButton); - - } - - protected boolean isAddButtonVisible() { - return getModelObject().isExpanded(); - } - - private void addValue(AjaxRequestTarget target) { -// ContainerWrapperFactory cwf = new ContainerWrapperFactory(getPageBase()); -// PrismContainerWrapper containerWrapper = getModelObject(); -// 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); - } - - private boolean isContainerMultivalue(){ - return true;// getModelObject().isVisible() && getModelObject().getItemDefinition().isMultiValue(); - } - - - public String getLabel() { - return getModelObject() != null ? getModelObject().getDisplayName() : ""; - } - -// @Override -// protected WebMarkupContainer initExpandCollapseButton(String contentAreaId) { -// Fragment expandCollapseFragment = new Fragment(contentAreaId, ID_EXPAND_COLLAPSE_FRAGMENT, this); -// -// ToggleIconButton expandCollapseButton = new ToggleIconButton(ID_EXPAND_COLLAPSE_BUTTON, -// GuiStyleConstants.CLASS_ICON_EXPAND_CONTAINER, GuiStyleConstants.CLASS_ICON_COLLAPSE_CONTAINER) { -// -// private static final long serialVersionUID = 1L; -// -// @Override -// public void onClick(AjaxRequestTarget target) { -// onExpandClick(target); -// } -// -// @Override -// public boolean isOn() { -// return PrismContainerHeaderPanel.this.getModelObject().isExpanded(); -// } -// }; -// expandCollapseButton.setOutputMarkupId(true); -// -// expandCollapseFragment.add(expandCollapseButton); -// -// return expandCollapseFragment; -// } -// -// private void onExpandClick(AjaxRequestTarget target) { -// -// PrismContainerWrapper wrapper = getModelObject(); -// wrapper.setExpanded(!wrapper.isExpanded()); -// onButtonClick(target); -// } -// -// @Override -// protected void initHeaderLabel(){ -// WebMarkupContainer labelContainer = new WebMarkupContainer(ID_LABEL_CONTAINER); -// labelContainer.setOutputMarkupId(true); -// -// add(labelContainer); -// -// String displayName = getLabel(); -// if (org.apache.commons.lang3.StringUtils.isEmpty(displayName)) { -// displayName = "displayName.not.set"; -// } -// -// StringResourceModel headerLabelModel = createStringResource(displayName); -// AjaxButton labelComponent = new AjaxButton(ID_LABEL, headerLabelModel) { -// private static final long serialVersionUID = 1L; -// @Override -// public void onClick(AjaxRequestTarget target) { -// onExpandClick(target); -// } -// }; -// labelComponent.setOutputMarkupId(true); -// labelComponent.add(AttributeAppender.append("style", "cursor: pointer;")); -// labelContainer.add(labelComponent); -// -// labelContainer.add(getHelpLabel()); -// -// } -// -// @Override -// protected String getHelpText() { -// return WebComponentUtil.loadHelpText(new Model>(getModelObject()), PrismContainerHeaderPanel.this); -// } -// -// @Override -// protected boolean isVisibleHelpText() { -// return true; -// } - -} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/ExpressionPropertyHeaderPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ExpressionPropertyHeaderPanel.html similarity index 100% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/ExpressionPropertyHeaderPanel.html rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ExpressionPropertyHeaderPanel.html diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/ExpressionPropertyHeaderPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ExpressionPropertyHeaderPanel.java similarity index 91% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/ExpressionPropertyHeaderPanel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ExpressionPropertyHeaderPanel.java index 0224a7d58e9..aad02d737be 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/ExpressionPropertyHeaderPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ExpressionPropertyHeaderPanel.java @@ -4,11 +4,12 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism.component; +package com.evolveum.midpoint.gui.impl.prism.panel; import com.evolveum.midpoint.gui.api.GuiStyleConstants; import com.evolveum.midpoint.gui.api.component.togglebutton.ToggleIconButton; -import com.evolveum.midpoint.gui.impl.prism.*; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismPropertyValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; import com.evolveum.midpoint.prism.PrismProperty; import com.evolveum.midpoint.prism.PrismPropertyDefinition; import com.evolveum.midpoint.prism.PrismPropertyValue; @@ -124,5 +125,13 @@ protected void removeExpressionValuePerformed(AjaxRequestTarget target){ } + @Override + protected void refreshPanel(AjaxRequestTarget target) { + + } + @Override + protected PrismPropertyValue createNewValue(PrismPropertyWrapper parent) { + return null; + } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ExpressionPropertyPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ExpressionPropertyPanel.html new file mode 100644 index 00000000000..003e3950040 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ExpressionPropertyPanel.html @@ -0,0 +1,31 @@ + + + + + +
+
+
+
+
+
+
+
+
+ + + + + + + + + + + + diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/ExpressionPropertyPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ExpressionPropertyPanel.java similarity index 87% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/ExpressionPropertyPanel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ExpressionPropertyPanel.java index 002ec29b60b..9435485fc6f 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/ExpressionPropertyPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ExpressionPropertyPanel.java @@ -1,137 +1,136 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.prism.component; - -import java.util.Collections; - -import org.apache.commons.collections.CollectionUtils; -import org.apache.wicket.Component; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.markup.html.list.ListItem; -import org.apache.wicket.markup.html.panel.Panel; -import org.apache.wicket.model.IModel; - -import com.evolveum.midpoint.gui.api.factory.GuiComponentFactory; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; -import com.evolveum.midpoint.gui.impl.prism.*; -import com.evolveum.midpoint.prism.PrismPropertyValue; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.prism.ValueStatus; -import com.evolveum.midpoint.web.component.util.VisibleBehaviour; -import com.evolveum.midpoint.web.util.ExpressionUtil; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType; - -/** - * @author katka - * - */ -public class ExpressionPropertyPanel extends PrismPropertyPanel { - - private static final long serialVersionUID = 1L; - - private static final Trace LOGGER = TraceManager.getTrace(ExpressionPropertyPanel.class); - - private static final String ID_HEADER = "header"; - - private boolean isExpanded; - - public ExpressionPropertyPanel(String id, IModel> model, ItemPanelSettings settings) { - super(id, model, settings); - isExpanded = model.getObject() != null && CollectionUtils.isNotEmpty(model.getObject().getValues()); - //todo how to set displayOrder ? to display expression property the last, in the same way as containers - } - - @Override - protected Panel createHeaderPanel() { - ExpressionWrapper expressionWrapper = (ExpressionWrapper) getModelObject(); - if (expressionWrapper != null && (expressionWrapper.isAssociationExpression() || expressionWrapper.isAttributeExpression())){ - return new ExpressionPropertyHeaderPanel(ID_HEADER, getModel()) { - private static final long serialVersionUID = 1L; - - @Override - protected void onExpandClick(AjaxRequestTarget target) { - super.onExpandClick(target); - isExpanded = !isExpanded; - target.add(ExpressionPropertyPanel.this); - } - - @Override - protected void addExpressionValuePerformed(AjaxRequestTarget target) { - ExpressionPropertyPanel.this.addExpressionValuePerformed(target); - } - - @Override - protected void removeExpressionValuePerformed(AjaxRequestTarget target){ - ExpressionPropertyPanel.this.getModelObject().getValues().clear(); - target.add(ExpressionPropertyPanel.this); - } - }; - } else { - return super.createHeaderPanel(); - } - } - - @Override - protected Component createValuePanel(ListItem> item, GuiComponentFactory factory, ItemVisibilityHandler visibilityHandler, - ItemEditabilityHandler editabilityHandler) { - Component expressionPanel = super.createValuePanel(item, factory, visibilityHandler, editabilityHandler); - expressionPanel.add(new VisibleBehaviour(() -> isExpanded)); - return expressionPanel; - } - - private void addExpressionValuePerformed(AjaxRequestTarget target){ - ExpressionWrapper expressionWrapper = (ExpressionWrapper) getModelObject(); - if (expressionWrapper.isAttributeExpression()){ - expressionValueAddPerformed(target, ExpressionValueTypes.LITERAL_VALUE_EXPRESSION); - } else { - ExpressionTypeSelectPopup expressionTypeSelectPopup = new ExpressionTypeSelectPopup(getPageBase().getMainPopupBodyId()) { - private static final long serialVersionUID = 1L; - - @Override - protected void addExpressionPerformed(AjaxRequestTarget target, ExpressionValueTypes expressionType) { - expressionValueAddPerformed(target, expressionType); - } - }; - getPageBase().showMainPopup(expressionTypeSelectPopup, target); - } - } - - private void expressionValueAddPerformed(AjaxRequestTarget target, ExpressionValueTypes expressionType){ - getPageBase().hideMainPopup(target); - try { - ExpressionType newExpressionValue = new ExpressionType(); - if (ExpressionValueTypes.SHADOW_REF_EXPRESSION.equals(expressionType)){ - ExpressionUtil.addShadowRefEvaluatorValue(newExpressionValue, null, getPrismContext()); - } else if (ExpressionValueTypes.ASSOCIATION_TARGET_SEARCH_EXPRESSION.equals(expressionType)){ - ExpressionUtil.getOrCreateAssociationTargetSearchValues(newExpressionValue, getPrismContext()); - } else if (ExpressionValueTypes.LITERAL_VALUE_EXPRESSION.equals(expressionType)){ - ExpressionUtil.updateLiteralExpressionValue(newExpressionValue, Collections.singletonList(""), getPrismContext()); - } - - WrapperContext context = new WrapperContext(null, null); - PrismPropertyValue expressionValue = getPageBase().getPrismContext().itemFactory().createPropertyValue(newExpressionValue); - PrismPropertyValueWrapper newExpressionValueWrapper = getPageBase().createValueWrapper(getModelObject(), expressionValue, ValueStatus.ADDED, context); - - getModelObject().getValues().clear(); - getModelObject().getValues().add(newExpressionValueWrapper); - getModelObject().getItem().setRealValue(newExpressionValue); - } catch (SchemaException ex){ - LOGGER.error("Unable to create new expression value: {}", ex.getLocalizedMessage()); - } - - target.add(ExpressionPropertyPanel.this); - - } - - @Override - protected void createButtons(ListItem> item) { - //nothing to do.. buttons are in the prism container panel header/ prism container value header - } - -} +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.prism.panel; + +import java.util.Collections; + +import com.evolveum.midpoint.gui.impl.prism.panel.component.ExpressionTypeSelectPopup; +import com.evolveum.midpoint.gui.impl.prism.panel.component.ExpressionValueTypes; +import com.evolveum.midpoint.gui.impl.prism.wrapper.ExpressionWrapper; + +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismPropertyValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; + +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.prism.PrismPropertyValue; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.component.prism.ValueStatus; +import com.evolveum.midpoint.web.component.util.VisibleBehaviour; +import com.evolveum.midpoint.web.util.ExpressionUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType; + +/** + * @author katka + * + */ +public class ExpressionPropertyPanel extends PrismPropertyPanel { + + private static final long serialVersionUID = 1L; + + private static final Trace LOGGER = TraceManager.getTrace(ExpressionPropertyPanel.class); + + private static final String ID_HEADER = "header"; + + private boolean isExpanded; + + public ExpressionPropertyPanel(String id, IModel> model, ItemPanelSettings settings) { + super(id, model, settings); + isExpanded = model.getObject() != null && CollectionUtils.isNotEmpty(model.getObject().getValues()); + //todo how to set displayOrder ? to display expression property the last, in the same way as containers + } + + @Override + protected Panel createHeaderPanel() { + ExpressionWrapper expressionWrapper = (ExpressionWrapper) getModelObject(); + if (expressionWrapper != null && (expressionWrapper.isAssociationExpression() || expressionWrapper.isAttributeExpression())){ + return new ExpressionPropertyHeaderPanel(ID_HEADER, getModel()) { + private static final long serialVersionUID = 1L; + + @Override + protected void onExpandClick(AjaxRequestTarget target) { + super.onExpandClick(target); + isExpanded = !isExpanded; + target.add(ExpressionPropertyPanel.this); + } + + @Override + protected void addExpressionValuePerformed(AjaxRequestTarget target) { + ExpressionPropertyPanel.this.addExpressionValuePerformed(target); + } + + @Override + protected void removeExpressionValuePerformed(AjaxRequestTarget target){ + ExpressionPropertyPanel.this.getModelObject().getValues().clear(); + target.add(ExpressionPropertyPanel.this); + } + }; + } else { + return super.createHeaderPanel(); + } + } + + @Override + protected Component createValuePanel(ListItem> item) { + Component expressionPanel = super.createValuePanel(item); + expressionPanel.add(new VisibleBehaviour(() -> isExpanded)); + return expressionPanel; + } + + private void addExpressionValuePerformed(AjaxRequestTarget target){ + ExpressionWrapper expressionWrapper = (ExpressionWrapper) getModelObject(); + if (expressionWrapper.isAttributeExpression()){ + expressionValueAddPerformed(target, ExpressionValueTypes.LITERAL_VALUE_EXPRESSION); + } else { + ExpressionTypeSelectPopup expressionTypeSelectPopup = new ExpressionTypeSelectPopup(getPageBase().getMainPopupBodyId()) { + private static final long serialVersionUID = 1L; + + @Override + protected void addExpressionPerformed(AjaxRequestTarget target, ExpressionValueTypes expressionType) { + expressionValueAddPerformed(target, expressionType); + } + }; + getPageBase().showMainPopup(expressionTypeSelectPopup, target); + } + } + + private void expressionValueAddPerformed(AjaxRequestTarget target, ExpressionValueTypes expressionType){ + getPageBase().hideMainPopup(target); + try { + ExpressionType newExpressionValue = new ExpressionType(); + if (ExpressionValueTypes.SHADOW_REF_EXPRESSION.equals(expressionType)){ + ExpressionUtil.addShadowRefEvaluatorValue(newExpressionValue, null, getPrismContext()); + } else if (ExpressionValueTypes.ASSOCIATION_TARGET_SEARCH_EXPRESSION.equals(expressionType)){ + ExpressionUtil.getOrCreateAssociationTargetSearchValues(newExpressionValue, getPrismContext()); + } else if (ExpressionValueTypes.LITERAL_VALUE_EXPRESSION.equals(expressionType)){ + ExpressionUtil.updateLiteralExpressionValue(newExpressionValue, Collections.singletonList(""), getPrismContext()); + } + + WrapperContext context = new WrapperContext(null, null); + PrismPropertyValue expressionValue = getPageBase().getPrismContext().itemFactory().createPropertyValue(newExpressionValue); + PrismPropertyValueWrapper newExpressionValueWrapper = getPageBase().createValueWrapper(getModelObject(), expressionValue, ValueStatus.ADDED, context); + + getModelObject().getValues().clear(); + getModelObject().getValues().add(newExpressionValueWrapper); + getModelObject().getItem().setRealValue(newExpressionValue); + } catch (SchemaException ex){ + LOGGER.error("Unable to create new expression value: {}", ex.getLocalizedMessage()); + } + + target.add(ExpressionPropertyPanel.this); + + } + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemHeaderPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemHeaderPanel.html similarity index 73% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemHeaderPanel.html rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemHeaderPanel.html index f3904693e2e..48cd27a443a 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemHeaderPanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemHeaderPanel.html @@ -9,7 +9,7 @@
-
+
+
- + +
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemHeaderPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemHeaderPanel.java similarity index 60% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemHeaderPanel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemHeaderPanel.java index 1aacc248a08..5afa0456dc6 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemHeaderPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemHeaderPanel.java @@ -4,21 +4,25 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.impl.prism.panel; + +import com.evolveum.midpoint.gui.api.prism.wrapper.*; + +import com.evolveum.midpoint.util.exception.SchemaException; + +import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; import org.apache.commons.lang3.StringUtils; import org.apache.wicket.AttributeModifier; import org.apache.wicket.Component; -import org.apache.wicket.markup.html.WebComponent; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; -import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.IModel; -import org.apache.wicket.model.LambdaModel; import org.apache.wicket.model.PropertyModel; import com.evolveum.midpoint.gui.api.component.BasePanel; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; import com.evolveum.midpoint.prism.Item; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismValue; @@ -36,14 +40,15 @@ public abstract class ItemHeaderPanel getModelObject().hasOutboundMapping())); -// labelContainer.add(hasOutbound); -// } - -// private void createPendingModification() { -// WebMarkupContainer hasPendingModification = new WebMarkupContainer(ID_PENDING_OPERATION); -// hasPendingModification.add(new VisibleEnableBehaviour() { -// private static final long serialVersionUID = 1L; -// -// @Override -// public boolean isVisible() { -// return hasPendingModification(model); -// } -// }); -// labelContainer.add(hasPendingModification); -// } -// -// private boolean hasPendingModification(IModel model) { -// ItemWrapperOld propertyWrapper = model.getObject(); -// ContainerWrapperImpl containerWrapper = propertyWrapper.getParent(); -// if (containerWrapper == null) { -// return false; // TODO - ok? -// } -// if (!containerWrapper.isMain()) { -// return false; -// } -// -// PrismContainer prismContainer = containerWrapper.getItem(); -// if (prismContainer.getCompileTimeClass() == null || -// !ShadowType.class.isAssignableFrom(prismContainer.getCompileTimeClass())) { -// return false; -// } -// -// PrismProperty objectChange = prismContainer.findProperty(ShadowType.F_OBJECT_CHANGE); -// if (objectChange == null || objectChange.getValue() == null) { -// return false; -// } -// -// ItemPath path = propertyWrapper.getItem().getPath(); -// ObjectDeltaType delta = (ObjectDeltaType) objectChange.getValue().getValue(); -// try { -// for (ItemDeltaType itemDelta : delta.getItemDelta()) { -// //noinspection unchecked -// ItemDelta iDelta = DeltaConvertor.createItemDelta(itemDelta, (Class) -// prismContainer.getCompileTimeClass(), prismContainer.getPrismContext()); -// if (iDelta.getPath().equivalent(path)) { -// return true; -// } -// } -// } catch (SchemaException ex) { -// LoggingUtils.logUnexpectedException(LOGGER, "Couldn't check if property has pending modification", ex); -// } -// -// return false; -// } - -// public String getLabelCssClass() { -// return " col-md-2 col-xs-12 prism-property-label "; -// } - public IModel getDeprecatedCss() { return () -> getModelObject() != null && getModelObject().isDeprecated() ? "text-decoration: line-through;" : "text-decoration: none;"; } + protected void initButtons() { + AjaxLink addButton = new AjaxLink(ID_ADD_BUTTON) { + private static final long serialVersionUID = 1L; - ///OLD - protected abstract void initButtons(); + @Override + public void onClick(AjaxRequestTarget target) { + addValue(target); + } + }; + addButton.add(new VisibleEnableBehaviour() { + + private static final long serialVersionUID = 1L; + + @Override + public boolean isEnabled() { + return isButtonEnabled(); + } + + @Override + public boolean isVisible() { + return isAddButtonVisible(); + } + }); + add(addButton); + + AjaxLink removeButton = new AjaxLink(ID_REMOVE_BUTTON) { + private static final long serialVersionUID = 1L; + + @Override + public void onClick(AjaxRequestTarget target) { + removeItem(target); + } + }; + removeButton.add(new VisibleBehaviour(() -> isButtonEnabled())); + add(removeButton); + } + + private void addValue(AjaxRequestTarget target) { + IW parentWrapper = getModelObject(); + try { + parentWrapper.add(createNewValue(parentWrapper), getPageBase()); + } catch (SchemaException e) { + getSession().error(getString("ItemHeaderPanel.value.add.failed", e.getMessage())); + LOGGER.error("Failed to add new value for {}, reason: {}", parentWrapper, e.getMessage(), e); + target.add(getPageBase().getFeedbackPanel()); + } + refreshPanel(target); + } + + private void removeItem(AjaxRequestTarget target) { + try { + getModelObject().removeAll(getPageBase()); + } catch (SchemaException e) { + LOGGER.error("Cannot remove value: {}", getModelObject()); + getSession().error("Cannot remove value "+ getModelObject()); + target.add(getPageBase().getFeedbackPanel()); + + } + refreshPanel(target); + } + + protected abstract V createNewValue(IW parent); + protected abstract void refreshPanel(AjaxRequestTarget target); + + + protected boolean isAddButtonVisible() { + return getModelObject() != null && getModelObject().isMultiValue(); + } + + protected boolean isButtonEnabled() { + return getModelObject() != null && !getModelObject().isReadOnly() && getModelObject().isMultiValue(); + } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemPanel.java new file mode 100644 index 00000000000..df994c96141 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemPanel.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.prism.panel; + +import java.util.Collection; +import java.util.Collections; + +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemEditabilityHandler; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemVisibilityHandler; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; +import com.evolveum.midpoint.prism.PrismValue; + +import com.evolveum.midpoint.web.page.admin.server.RefreshableTabPanel; + +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.list.ListView; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.PropertyModel; + +import com.evolveum.midpoint.gui.api.component.BasePanel; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.impl.component.data.column.AbstractItemWrapperColumnPanel; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.component.util.VisibleBehaviour; + +/** + * @author katka + * + */ +public abstract class ItemPanel, IW extends ItemWrapper> extends BasePanel implements RefreshableTabPanel { + + private static final long serialVersionUID = 1L; + + private static final Trace LOGGER = TraceManager.getTrace(ItemPanel.class); + + private static final String DOT_CLASS = ItemPanel.class.getName() + ""; + + private static final String ID_VALUES = "values"; + + private ItemPanelSettings itemPanelSettings; + + + public ItemPanel(String id, IModel model, ItemPanelSettings itemPanelSettings) { + super(id, model); + this.itemPanelSettings = itemPanelSettings; + } + + @Override + protected void onInitialize() { + super.onInitialize(); + initLayout(); + setOutputMarkupId(true); + } + + private void initLayout() { + + //ugly hack TODO FIME - prism context is lost during srialization/deserialization.. find better way how to do it. + if (getModelObject() != null) { + getModelObject().revive(getPrismContext()); + } + + Panel headerPanel = createHeaderPanel(); + headerPanel.add(new VisibleBehaviour(() -> getHeaderVisibility())); + add(headerPanel); + + ListView valuesPanel = createValuesPanel(); + add(valuesPanel); + + } + + protected boolean getHeaderVisibility() { + if (!isHeaderVisible()) { + return false; + } + return getParent().findParent(AbstractItemWrapperColumnPanel.class) == null; + } + + protected abstract Panel createHeaderPanel(); + + protected ListView createValuesPanel() { + + ListView values = new ListView(ID_VALUES, new PropertyModel<>(getModel(), "values")) { + + private static final long serialVersionUID = 1L; + + @Override + protected void populateItem(ListItem item) { + + + Component panel = createValuePanel(item); + panel.add(new VisibleBehaviour(() -> item.getModelObject().isVisible())); + } + + }; + + return values; + } + + protected void removeValue(VW valueToRemove, AjaxRequestTarget target) throws SchemaException { + LOGGER.debug("Removing value of {}", valueToRemove); + + getModelObject().remove(valueToRemove, getPageBase()); + target.add(ItemPanel.this); + } + + // VALUE REGION + + protected abstract Component createValuePanel(ListItem item); + + + protected abstract PV createNewValue(IW itemWrapper); + + public ItemVisibilityHandler getVisibilityHandler() { + if (itemPanelSettings == null) { + return null; + } + return itemPanelSettings.getVisibilityHandler(); + } + + public ItemEditabilityHandler getEditabilityHandler() { + if (itemPanelSettings == null) { + return null; + } + return itemPanelSettings.getEditabilityHandler(); + } + + protected boolean isHeaderVisible() { + if (itemPanelSettings == null) { + return true; + } + + return itemPanelSettings.isHeaderVisible(); + } + + public ItemPanelSettings getSettings() { + return itemPanelSettings; + } + + @Override + public Collection getComponentsToUpdate() { + return Collections.singleton(this); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemPanelSettings.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemPanelSettings.java similarity index 68% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemPanelSettings.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemPanelSettings.java index ec7d74ee028..dd99514c3ca 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemPanelSettings.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemPanelSettings.java @@ -1,10 +1,14 @@ /* - * Copyright (c) 2010-2019 Evolveum and contributors + * Copyright (c) 2020 Evolveum and contributors * * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.impl.prism.panel; + +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemEditabilityHandler; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemMandatoryHandler; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemVisibilityHandler; import java.io.Serializable; @@ -12,10 +16,12 @@ public class ItemPanelSettings implements Serializable { private ItemVisibilityHandler visibilityHandler; private ItemEditabilityHandler editabilityHandler = wrapper -> true; - private boolean showOnTopLevel; private boolean headerVisible = true; private ItemMandatoryHandler mandatoryHandler; + ItemPanelSettings() { + + } public ItemVisibilityHandler getVisibilityHandler() { return visibilityHandler; @@ -33,14 +39,6 @@ public void setEditabilityHandler(ItemEditabilityHandler editabilityHandler) { this.editabilityHandler = editabilityHandler; } - public boolean isShowOnTopLevel() { - return showOnTopLevel; - } - - void setShowOnTopLevel(boolean showOnTopLevel) { - this.showOnTopLevel = showOnTopLevel; - } - public boolean isHeaderVisible() { return headerVisible; } @@ -56,5 +54,12 @@ public ItemMandatoryHandler getMandatoryHandler() { public void setMandatoryHandler(ItemMandatoryHandler mandatoryHandler) { this.mandatoryHandler = mandatoryHandler; } -} + public ItemPanelSettings copy() { + return new ItemPanelSettingsBuilder() + .editabilityHandler(editabilityHandler) + .visibilityHandler(visibilityHandler) + .mandatoryHandler(mandatoryHandler) + .build(); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemPanelSettingsBuilder.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemPanelSettingsBuilder.java new file mode 100644 index 00000000000..961cb173ccf --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemPanelSettingsBuilder.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.prism.panel; + +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemEditabilityHandler; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemMandatoryHandler; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemVisibilityHandler; + +public class ItemPanelSettingsBuilder { + + private ItemPanelSettings settings; + + public ItemPanelSettingsBuilder() { + settings = new ItemPanelSettings(); + } + + public ItemPanelSettingsBuilder visibilityHandler(ItemVisibilityHandler handler) { + settings.setVisibilityHandler(handler); + return this; + } + + public ItemPanelSettingsBuilder editabilityHandler(ItemEditabilityHandler handler) { + settings.setEditabilityHandler(handler); + return this; + } + + public ItemPanelSettingsBuilder mandatoryHandler(ItemMandatoryHandler handler) { + settings.setMandatoryHandler(handler); + return this; + } + + public ItemPanelSettingsBuilder headerVisibility(boolean headerVisibility) { + settings.setHeaderVisible(headerVisibility); + return this; + } + + public ItemPanelSettings build() { + return settings; + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemWrapperComparator.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemWrapperComparator.java similarity index 84% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemWrapperComparator.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemWrapperComparator.java index bb1c20ee974..2f6b1a427a4 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ItemWrapperComparator.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ItemWrapperComparator.java @@ -1,23 +1,23 @@ /* - * Copyright (c) 2010-2019 Evolveum and contributors + * Copyright (c) 2020 Evolveum and contributors * * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.impl.prism.panel; + +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import java.text.Collator; import java.util.Comparator; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; - /** * @author katka * */ -public class ItemWrapperComparator implements Comparator{ +public class ItemWrapperComparator implements Comparator { - private Collator collator = null; + private Collator collator; private boolean sorted; public ItemWrapperComparator(Collator collator, boolean sorted) { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/PolyStringEditorPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PolyStringEditorPanel.html similarity index 100% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/PolyStringEditorPanel.html rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PolyStringEditorPanel.html diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/PolyStringEditorPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PolyStringEditorPanel.java similarity index 99% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/PolyStringEditorPanel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PolyStringEditorPanel.java index fbf5ddc5d8c..192e4a2941d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/PolyStringEditorPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PolyStringEditorPanel.java @@ -4,7 +4,7 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism.component; +package com.evolveum.midpoint.gui.impl.prism.panel; import com.evolveum.midpoint.gui.api.component.autocomplete.AutoCompleteTextPanel; import com.evolveum.midpoint.gui.api.model.LoadableModel; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerColumnHeaderPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerColumnHeaderPanel.java similarity index 64% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerColumnHeaderPanel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerColumnHeaderPanel.java index 4ab4b896017..576ae33ed33 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerColumnHeaderPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerColumnHeaderPanel.java @@ -4,27 +4,18 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.impl.prism.panel; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.ajax.markup.html.AjaxLink; -import org.apache.wicket.behavior.AttributeAppender; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.model.IModel; -import com.evolveum.midpoint.gui.api.GuiStyleConstants; -import com.evolveum.midpoint.gui.api.component.togglebutton.ToggleIconButton; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContainer; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.web.component.AjaxButton; -import com.evolveum.midpoint.web.component.prism.ValueStatus; -import com.evolveum.midpoint.web.component.util.VisibleBehaviour; /** * @author skublik @@ -37,9 +28,7 @@ public class PrismContainerColumnHeaderPanel extends It public PrismContainerColumnHeaderPanel(String id, IModel> model) { super(id, model); } - @Override - protected void initButtons() { - } + @Override protected Component createTitle(IModel label) { @@ -47,4 +36,24 @@ protected Component createTitle(IModel label) { labelComponent.setOutputMarkupId(true); return labelComponent; } + + @Override + protected void refreshPanel(AjaxRequestTarget target) { + + } + + @Override + protected PrismContainerValue createNewValue(PrismContainerWrapper parent) { + return null; + } + + @Override + protected boolean isAddButtonVisible() { + return false; + } + + @Override + protected boolean isButtonEnabled() { + return false; + } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerHeaderPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerHeaderPanel.html similarity index 81% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerHeaderPanel.html rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerHeaderPanel.html index 3c8f1f23886..b201a61a809 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerHeaderPanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerHeaderPanel.html @@ -29,8 +29,11 @@
- +
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerHeaderPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerHeaderPanel.java similarity index 51% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerHeaderPanel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerHeaderPanel.java index 8a3bec3a916..b85ff10933e 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerHeaderPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerHeaderPanel.java @@ -4,27 +4,21 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.impl.prism.panel; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.behavior.AttributeAppender; import org.apache.wicket.model.IModel; import com.evolveum.midpoint.gui.api.GuiStyleConstants; import com.evolveum.midpoint.gui.api.component.togglebutton.ToggleIconButton; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContainer; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.web.component.AjaxButton; -import com.evolveum.midpoint.web.component.prism.ValueStatus; -import com.evolveum.midpoint.web.component.util.VisibleBehaviour; -import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; /** * @author katka @@ -34,8 +28,6 @@ public class PrismContainerHeaderPanel extends ItemHead private static final long serialVersionUID = 1L; - private static final String ID_ADD_BUTTON = "addButton"; - private static final String ID_EXPAND_COLLAPSE_FRAGMENT = "expandCollapseFragment"; private static final String ID_EXPAND_COLLAPSE_BUTTON = "expandCollapseButton"; @@ -45,58 +37,12 @@ public PrismContainerHeaderPanel(String id, IModel> mod @Override protected void initButtons() { - AjaxLink addButton = new AjaxLink(ID_ADD_BUTTON) { - private static final long serialVersionUID = 1L; - @Override - public void onClick(AjaxRequestTarget target) { - addValue(target); - } - }; - addButton.add(new VisibleEnableBehaviour() { - - private static final long serialVersionUID = 1L; - - @Override - public boolean isEnabled() { - return isAddButtonEnable(); - } - - @Override - public boolean isVisible() { - return isAddButtonVisible(); - } - }); - add(addButton); - - - initExpandCollapseButton(); + super.initButtons(); + initExpandCollapseButton(); //TODO: sorting } - private void addValue(AjaxRequestTarget target) { - PrismContainerWrapper parentWrapper = getModelObject(); - WrapperContext ctx = new WrapperContext(null, null); - ctx.setShowEmpty(true); - try { - PrismContainerValueWrapper valueWrapper = getPageBase().createValueWrapper(parentWrapper, parentWrapper.getItem().createNewValue(), ValueStatus.ADDED, ctx); - parentWrapper.getValues().add(valueWrapper); - } catch (SchemaException e) { - // TODO error handling - } - PrismContainerPanel parentPanel = findParent(PrismContainerPanel.class); - target.add(parentPanel); - } - - - - private boolean isAddButtonVisible() { - return getModelObject() != null && getModelObject().isExpanded() && getModelObject().isMultiValue(); - } - - private boolean isAddButtonEnable() { - return getModelObject() != null && !getModelObject().isReadOnly(); - } @Override protected Component createTitle(IModel label) { @@ -133,12 +79,26 @@ public boolean isOn() { add(expandCollapseButton); } - private void onExpandClick(AjaxRequestTarget target) { + protected void onExpandClick(AjaxRequestTarget target) { + } + + @Override + protected PrismContainerValue createNewValue(PrismContainerWrapper parent) { + return parent.getItem().createNewValue(); + } + + @Override + protected void refreshPanel(AjaxRequestTarget target) { - PrismContainerWrapper wrapper = getModelObject(); - wrapper.setExpanded(!wrapper.isExpanded()); - target.add(getParent()); } + @Override + protected boolean isButtonEnabled() { + return super.isButtonEnabled() && getModelObject().isExpanded(); + } + @Override + protected boolean isAddButtonVisible() { + return super.isAddButtonVisible() && getModelObject().isExpanded(); + } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerPanel.html similarity index 100% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerPanel.html rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerPanel.html diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerPanel.java new file mode 100644 index 00000000000..cb475ed5b9a --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerPanel.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.prism.panel; + +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.util.exception.SchemaException; + +import org.apache.wicket.AttributeModifier; +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; + +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.prism.Containerable; + +/** + * @author katka + * + */ +public class PrismContainerPanel extends ItemPanel, PrismContainerWrapper>{ + + private static final long serialVersionUID = 1L; + + private static final String ID_HEADER = "header"; + + /** + * @param id + * @param model + */ + public PrismContainerPanel(String id, IModel> model, ItemPanelSettings settings) { + super(id, model, settings); + } + + @Override + protected void onInitialize() { + super.onInitialize(); + + + add(AttributeModifier.append("class", () -> { + + if (getModelObject() != null && getModelObject().isMultiValue()) { + return " multivalue-container"; + } + return ""; + })); + + } + + @Override + protected Panel createHeaderPanel() { + return new PrismContainerHeaderPanel(ID_HEADER, getModel()) { + @Override + protected void onExpandClick(AjaxRequestTarget target) { + PrismContainerWrapper wrapper = PrismContainerPanel.this.getModelObject(); + wrapper.setExpanded(!wrapper.isExpanded()); + target.add(PrismContainerPanel.this); + } + + @Override + protected void refreshPanel(AjaxRequestTarget target) { + target.add(PrismContainerPanel.this); + } + }; + } + + @Override + protected boolean getHeaderVisibility() { + if(!super.getHeaderVisibility()) { + return false; + } + return getModelObject() != null && getModelObject().isMultiValue(); + } + + @Override + protected Component createValuePanel(ListItem> item) { + PrismContainerValuePanel> panel = new PrismContainerValuePanel>("value", item.getModel(), getSettings().copy()) { + + @Override + protected void removeValue(PrismContainerValueWrapper valueToRemove, AjaxRequestTarget target) throws SchemaException { + PrismContainerPanel.this.removeValue(valueToRemove, target); + } + }; + item.add(panel); + return panel; + } + + @Override + protected PV createNewValue(PrismContainerWrapper itemWrapper) { + return (PV) itemWrapper.getItem().createNewValue(); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerValueHeaderPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerValueHeaderPanel.html similarity index 100% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerValueHeaderPanel.html rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerValueHeaderPanel.html diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerValuePanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerValuePanel.html new file mode 100644 index 00000000000..cdaa0327134 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerValuePanel.html @@ -0,0 +1,57 @@ + + + + + +
+ +
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+ +
+ + + diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerValuePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerValuePanel.java similarity index 70% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerValuePanel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerValuePanel.java index 22540f5543f..9e9791bf2dc 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismContainerValuePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismContainerValuePanel.java @@ -4,34 +4,33 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.impl.prism.panel; import java.text.Collator; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Locale; import javax.xml.namespace.QName; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.util.WebPrismUtil; +import com.evolveum.midpoint.gui.api.prism.wrapper.*; +import com.evolveum.midpoint.gui.impl.factory.panel.ItemPanelContext; +import com.evolveum.midpoint.gui.impl.factory.panel.PrismContainerPanelContext; +import com.evolveum.midpoint.gui.impl.prism.panel.component.ListContainersPopup; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ResourceAttributeWrapper; import com.evolveum.midpoint.prism.*; -import com.evolveum.midpoint.web.component.prism.ItemVisibility; - -import com.evolveum.midpoint.xml.ns._public.common.common_3.MetadataType; - import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.wicket.AttributeModifier; +import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.behavior.AttributeAppender; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.list.ListItem; -import org.apache.wicket.markup.html.list.ListItemModel; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.IModel; @@ -41,18 +40,15 @@ import org.apache.wicket.model.StringResourceModel; import com.evolveum.midpoint.gui.api.GuiStyleConstants; -import com.evolveum.midpoint.gui.api.component.BasePanel; import com.evolveum.midpoint.gui.api.component.togglebutton.ToggleIconButton; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.schema.result.OperationResult; 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.AjaxButton; import com.evolveum.midpoint.web.component.prism.ValueStatus; -import com.evolveum.midpoint.web.component.util.EnableBehaviour; import com.evolveum.midpoint.web.component.util.VisibleBehaviour; import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; import com.evolveum.midpoint.web.util.InfoTooltipBehavior; @@ -61,7 +57,7 @@ * @author katka * */ -public class PrismContainerValuePanel> extends BasePanel{ +public class PrismContainerValuePanel> extends PrismValuePanel, CVW> { private static final long serialVersionUID = 1L; @@ -77,50 +73,22 @@ public class PrismContainerValuePanel model, ItemPanelSettings settings) { - super(id, model); - this.settings = settings; + super(id, model, settings); } @Override - public boolean isVisible() { - CVW modelObject = getModelObject(); - if (modelObject == null) { - return false; - } - - if (ValueStatus.DELETED == modelObject.getStatus()) { - return false; - } - - ItemWrapper parent = modelObject.getParent(); - if (!PrismContainerWrapper.class.isAssignableFrom(parent.getClass())) { - return false; - } - - if (MetadataType.COMPLEX_TYPE.equals(parent.getTypeName()) && (modelObject.isShowMetadata())) { - return false; - } - - if (isShowOnTopLevel()) { - return true; - } - - if (!isShowOnTopLevel() && !((PrismContainerWrapper) parent).isExpanded()) { // && parent.isMultiValue()) { - return false; - } - return ((PrismContainerWrapper) parent).isExpanded(); + protected PC createPanelCtx(IModel> wrapper) { + return (PC) new PrismContainerPanelContext(wrapper); } @Override protected void onInitialize() { super.onInitialize(); - initLayout(); - setOutputMarkupId(true); add(AttributeModifier.append("class", () -> { String cssClasses = ""; @@ -135,16 +103,12 @@ protected void onInitialize() { } - private void initLayout() { - initHeader(); - initValues(); - } - - private void initHeader() { + @Override + protected void addToHeader(WebMarkupContainer header) { WebMarkupContainer labelContainer = new WebMarkupContainer(ID_LABEL_CONTAINER); labelContainer.setOutputMarkupId(true); - add(labelContainer); + header.add(labelContainer); LoadableDetachableModel headerLabelModel = getLabelModel(); AjaxButton labelComponent = new AjaxButton(ID_LABEL, headerLabelModel) { @@ -161,7 +125,7 @@ public void onClick(AjaxRequestTarget target) { labelContainer.add(getHelpLabel()); - initButtons(); + initButtons(header); //TODO always visible if isObject } @@ -170,15 +134,21 @@ protected LoadableDetachableModel getLabelModel() { return getPageBase().createStringResource(getModel().getObject().getDisplayName()); } - private void initValues() { - - createNonContainersPanel(); + @Override + protected Component createDefaultPanel(String id) { + WebMarkupContainer defaultPanel = new WebMarkupContainer(id); + defaultPanel.add(createNonContainersPanel()); - createContainersPanel(); + defaultPanel.add(createContainersPanel()); + return defaultPanel; + } + @Override + protected PV createNewValue(PrismContainerWrapper itemWrapper) { + return (PV) itemWrapper.getItem().createNewValue(); } - private , ID extends ItemDefinition, IW extends ItemWrapper> void createNonContainersPanel() { + private > WebMarkupContainer createNonContainersPanel() { WebMarkupContainer propertiesLabel = new WebMarkupContainer(ID_PROPERTIES_LABEL); propertiesLabel.setOutputMarkupId(true); @@ -195,7 +165,7 @@ protected void populateItem(final ListItem item) { }; properties.setOutputMarkupId(true); add(propertiesLabel); - propertiesLabel.add(properties); + propertiesLabel.add(properties); AjaxButton labelShowEmpty = new AjaxButton(ID_SHOW_EMPTY_BUTTON) { private static final long serialVersionUID = 1L; @@ -221,10 +191,13 @@ public boolean isVisible() { && getModelObject().isExpanded();// && !model.getObject().isShowEmpty(); } }); - add(labelShowEmpty); + propertiesLabel.add(labelShowEmpty); + return propertiesLabel; } - private void createContainersPanel() { + private WebMarkupContainer createContainersPanel() { + WebMarkupContainer containersLable = new WebMarkupContainer(ID_CONTAINERS_LABEL); + add(containersLable); ListView> containers = new ListView>("containers", new PropertyModel<>(getModel(), "containers")) { private static final long serialVersionUID = 1L; @@ -236,11 +209,12 @@ protected void populateItem(final ListItem> item) { containers.setReuseItems(true); containers.setOutputMarkupId(true); - add(containers); + containersLable.add(containers); + return containersLable; } - private > IModel> createNonContainerWrappersModel() { + private > IModel> createNonContainerWrappersModel() { return new IModel>() { private static final long serialVersionUID = 1L; @@ -252,9 +226,9 @@ public List getObject() { }; } - private > List getNonContainerWrappers() { + private > List getNonContainerWrappers() { CVW containerValueWrapper = getModelObject(); - List> nonContainers = containerValueWrapper.getNonContainers(); + List> nonContainers = containerValueWrapper.getNonContainers(); Locale locale = WebModelServiceUtils.getLocale(); if (locale == null) { @@ -269,8 +243,8 @@ private > List getNonContainerWrappers() { int visibleProperties = 0; - for (ItemWrapper item : nonContainers) { - if (item.isVisible(containerValueWrapper, getVisibilityHandler())) { + for (ItemWrapper item : nonContainers) { + if (item.isVisible(getModelObject(), getVisibilityHandler())) { visibleProperties++; } @@ -286,38 +260,7 @@ private > List getNonContainerWrappers() { return (List) nonContainers; } - private ItemVisibilityHandler getVisibilityHandler() { - if (settings == null) { - return null; - } - - return settings.getVisibilityHandler(); - } - - private ItemEditabilityHandler getReadabilityHandler() { - if (settings == null) { - return null; - } - - return settings.getEditabilityHandler(); - } - - private ItemMandatoryHandler getMandatoryHandler() { - if (settings == null) { - return null; - } - return settings.getMandatoryHandler(); - } - - private boolean isShowOnTopLevel() { - if (settings == null) { - return false; - } - - return settings.isShowOnTopLevel(); - } - - private > void populateNonContainer(ListItem item) { + private > void populateNonContainer(ListItem item) { item.setOutputMarkupId(true); IW itemWrapper = item.getModelObject(); try { @@ -326,43 +269,42 @@ private > void populateNonContainer(ListItem typeName = new QName("ResourceAttributeDefinition"); } - ItemPanelSettingsBuilder builder = new ItemPanelSettingsBuilder() - .visibilityHandler(getVisibilityHandler()) - .editabilityHandler(getReadabilityHandler()) - .mandatoryHandler(getMandatoryHandler()) - .showOnTopLevel(isShowOnTopLevel()); - Panel panel = getPageBase().initItemPanel("property", typeName, item.getModel(), builder.build()); + Panel panel = getPageBase().initItemPanel("property", typeName, item.getModel(), getSettings().copy()); panel.setOutputMarkupId(true); + panel.add(AttributeModifier.append("class", appendStyleClassModel(item.getModel()))); panel.add(new VisibleEnableBehaviour() { - - private static final long serialVersionUID = 1L; - - //TODO decide if we need to set enable behavior here - //see also ItemPanel.getEnableBehaviourOfValuePanel(), may be it's enough -// @Override -// public boolean isEnabled() { -// return !item.getModelObject().isReadOnly(); -// } - @Override public boolean isVisible() { - CVW parent = PrismContainerValuePanel.this.getModelObject(); - return item.getModelObject().isVisible(parent, getVisibilityHandler()); + return itemWrapper.isVisible(getModelObject(), getVisibilityHandler()); + } + + @Override + public boolean isEnabled() { + return !itemWrapper.isReadOnly(); } }); item.add(panel); } catch (SchemaException e1) { throw new SystemException("Cannot instantiate " + itemWrapper.getTypeName()); } - - item.add(AttributeModifier.append("class", createStyleClassModel(item.getModel()))); } private void populateContainer(ListItem> container) { PrismContainerWrapper itemWrapper = container.getModelObject(); try { - Panel panel = getPageBase().initItemPanel("container", itemWrapper.getTypeName(), container.getModel(), settings); + Panel panel = getPageBase().initItemPanel("container", itemWrapper.getTypeName(), container.getModel(), getSettings().copy()); panel.setOutputMarkupId(true); + panel.add(new VisibleEnableBehaviour() { + @Override + public boolean isVisible() { + return itemWrapper.isVisible(getModelObject(), getVisibilityHandler()); + } + + @Override + public boolean isEnabled() { + return !itemWrapper.isReadOnly(); + } + }); container.add(panel); } catch (SchemaException e) { throw new SystemException("Cannot instantiate panel for: " + itemWrapper.getDisplayName()); @@ -377,29 +319,28 @@ private StringResourceModel getNameOfShowEmptyButton() { private void onShowEmptyClick(AjaxRequestTarget target) { - PrismContainerValueWrapper wrapper = getModelObject(); + CVW wrapper = getModelObject(); wrapper.setShowEmpty(!wrapper.isShowEmpty()); refreshPanel(target); } - private > IModel createStyleClassModel(final IModel wrapper) { + private > IModel appendStyleClassModel(final IModel wrapper) { return new IModel() { private static final long serialVersionUID = 1L; @Override public String getObject() { - ItemWrapper property = wrapper.getObject(); + ItemWrapper property = wrapper.getObject(); return property.isStripe() ? "stripe" : null; } }; } - private void initButtons() { - initExpandCollapseButton(); - initMetadataButton(); - initSortButton(); - initAddMoreButton(); - initRemoveButton(); + private void initButtons(WebMarkupContainer header) { + header.add(createExpandCollapseButton()); + header.add(createMetadataButton()); + header.add(createSortButton()); + header.add(createAddMoreButton()); } private void onExpandClick(AjaxRequestTarget target) { @@ -412,14 +353,14 @@ private void onExpandClick(AjaxRequestTarget target) { protected Label getHelpLabel() { Label help = new Label(ID_HELP); - help.add(AttributeModifier.replace("title", LambdaModel.of(getModel(), CVW::getHelpText))); + help.add(AttributeModifier.replace("title", LambdaModel.of(getModel(), PrismContainerValueWrapper::getHelpText))); help.add(new InfoTooltipBehavior()); help.add(new VisibleBehaviour(() -> StringUtils.isNotEmpty(getModelObject().getHelpText()))); help.setOutputMarkupId(true); return help; } - private void initMetadataButton() { + private ToggleIconButton createMetadataButton() { ToggleIconButton showMetadataButton = new ToggleIconButton(ID_SHOW_METADATA, GuiStyleConstants.CLASS_ICON_SHOW_METADATA, GuiStyleConstants.CLASS_ICON_SHOW_METADATA) { private static final long serialVersionUID = 1L; @@ -440,11 +381,10 @@ public boolean isOn() { showMetadataButton.add(new VisibleBehaviour(() -> getModelObject().hasMetadata() && shouldBeButtonsShown())); showMetadataButton.setOutputMarkupId(true); showMetadataButton.setOutputMarkupPlaceholderTag(true); - add(showMetadataButton); - + return showMetadataButton; } - private void initSortButton() { + private ToggleIconButton createSortButton() { ToggleIconButton sortPropertiesButton = new ToggleIconButton(ID_SORT_PROPERTIES, GuiStyleConstants.CLASS_ICON_SORT_ALPHA_ASC, GuiStyleConstants.CLASS_ICON_SORT_AMOUNT_ASC) { @@ -463,10 +403,10 @@ public boolean isOn() { sortPropertiesButton.add(new VisibleBehaviour(() -> shouldBeButtonsShown())); sortPropertiesButton.setOutputMarkupId(true); sortPropertiesButton.setOutputMarkupPlaceholderTag(true); - add(sortPropertiesButton); + return sortPropertiesButton; } - private void initAddMoreButton() { + private AjaxLink createAddMoreButton() { AjaxLink addChildContainerButton = new AjaxLink(ID_ADD_CHILD_CONTAINER, new StringResourceModel("PrismContainerValuePanel.addMore")) { private static final long serialVersionUID = 1L; @@ -500,8 +440,7 @@ public boolean isVisible() { }); addChildContainerButton.setOutputMarkupId(true); addChildContainerButton.setOutputMarkupPlaceholderTag(true); - add(addChildContainerButton); - + return addChildContainerButton; } private void initMoreContainersPopup(AjaxRequestTarget parentTarget) { @@ -544,53 +483,6 @@ private void prepareNewContainers(AjaxRequestTarget target, List removeContainerButton = new AjaxLink(ID_REMOVE_CONTAINER) { - private static final long serialVersionUID = 1L; - - @Override - public void onClick(AjaxRequestTarget target) { - try { - removePerformed(PrismContainerValuePanel.this.getModelObject(), target); - } catch (SchemaException e) { - e.printStackTrace(); - } - } - - }; - - removeContainerButton.add(new VisibleEnableBehaviour() { - - private static final long serialVersionUID = 1L; - - @Override - public boolean isEnabled() { - if (getModelObject() != null) { - if(getModelObject().getParent() != null) { - return !getModelObject().getParent().isReadOnly(); - } else { - return !getModelObject().isReadOnly(); - } - } - return false; - } - - @Override - public boolean isVisible() { - if (getModelObject() instanceof PrismObjectValueWrapper) { - return false; - } - return shouldBeButtonsShown(); - } - }); - add(removeContainerButton); - - } - - protected void removePerformed(CVW containerValueWrapper, AjaxRequestTarget target) throws SchemaException { - - } - private boolean shouldBeButtonsShown() { return getModelObject().isExpanded(); } @@ -614,7 +506,7 @@ private void refreshPanel(AjaxRequestTarget target) { target.add(getPageBase().getFeedbackPanel()); } - protected void initExpandCollapseButton() { + protected ToggleIconButton createExpandCollapseButton() { ToggleIconButton expandCollapseButton = new ToggleIconButton(ID_EXPAND_COLLAPSE_BUTTON, GuiStyleConstants.CLASS_ICON_EXPAND_CONTAINER, GuiStyleConstants.CLASS_ICON_COLLAPSE_CONTAINER) { @@ -631,6 +523,16 @@ public boolean isOn() { } }; expandCollapseButton.setOutputMarkupId(true); - add(expandCollapseButton); + return expandCollapseButton; + } + + @Override + protected void removeValue(CVW valueToRemove, AjaxRequestTarget target) throws SchemaException { + throw new UnsupportedOperationException("Must be implemented in calling panel"); + } + + @Override + protected boolean isRemoveButtonVisible() { + return super.isRemoveButtonVisible() && getModelObject().isExpanded() && !(getModelObject() instanceof PrismObjectValueWrapper); } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismObjectValuePanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismObjectValuePanel.html similarity index 100% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismObjectValuePanel.html rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismObjectValuePanel.html diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismObjectValuePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismObjectValuePanel.java similarity index 84% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismObjectValuePanel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismObjectValuePanel.java index c97c3456297..1cd96275c0d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismObjectValuePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismObjectValuePanel.java @@ -1,56 +1,55 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.impl.prism; - -import com.evolveum.midpoint.xml.ns._public.common.common_3.VirtualContainersSpecificationType; -import org.apache.wicket.model.IModel; -import org.apache.wicket.model.PropertyModel; - -import com.evolveum.midpoint.gui.api.component.BasePanel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; - -import java.util.List; - -/** - * @author katka - * - */ -public class PrismObjectValuePanel extends BasePanel> { - - private static final long serialVersionUID = 1L; - - private static final String ID_VALUE = "value"; - private static final String ID_VIRTUAL_CONTAINERS = "virtualContainers"; - - private ItemPanelSettings settings; - - public PrismObjectValuePanel(String id, IModel> model, ItemPanelSettings settings) { - super(id, model); - this.settings = settings; - } - - @Override - protected void onInitialize() { - super.onInitialize(); - initLayout(); - setOutputMarkupId(true); - } - - private void initLayout() { - createValuePanel(ID_VALUE, new PropertyModel<>(getModel(), "value")); - } - - protected void createValuePanel(String panelId, IModel> valueModel) { - - PrismContainerValuePanel> valueWrapper = new PrismContainerValuePanel<>(panelId, valueModel, - settings); - valueWrapper.setOutputMarkupId(true); - add(valueWrapper); - - } -} +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.prism.panel; + +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectValueWrapper; + +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.PropertyModel; + +import com.evolveum.midpoint.gui.api.component.BasePanel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; + +/** + * @author katka + * + */ +public class PrismObjectValuePanel extends BasePanel> { + + private static final long serialVersionUID = 1L; + + private static final String ID_VALUE = "value"; + private static final String ID_VIRTUAL_CONTAINERS = "virtualContainers"; + + private ItemPanelSettings settings; + + public PrismObjectValuePanel(String id, IModel> model, ItemPanelSettings settings) { + super(id, model); + this.settings = settings; + } + + @Override + protected void onInitialize() { + super.onInitialize(); + initLayout(); + setOutputMarkupId(true); + } + + private void initLayout() { + createValuePanel(ID_VALUE, new PropertyModel<>(getModel(), "value")); + } + + protected void createValuePanel(String panelId, IModel> valueModel) { + + PrismContainerValuePanel> valueWrapper = new PrismContainerValuePanel<>(panelId, valueModel, + settings); + valueWrapper.setOutputMarkupId(true); + add(valueWrapper); + + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyHeaderPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismPropertyHeaderPanel.java similarity index 72% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyHeaderPanel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismPropertyHeaderPanel.java index 360785e64f3..5ddf32c3bee 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismPropertyHeaderPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismPropertyHeaderPanel.java @@ -4,14 +4,14 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.impl.prism.panel; + +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; -import org.apache.wicket.AttributeModifier; import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.markup.html.basic.Label; -import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.IModel; -import org.apache.wicket.model.LambdaModel; import com.evolveum.midpoint.prism.PrismProperty; import com.evolveum.midpoint.prism.PrismPropertyDefinition; @@ -43,9 +43,12 @@ protected Component createTitle(IModel label) { } @Override - protected void initButtons() { - // nothing to do - + protected PrismPropertyValue createNewValue(PrismPropertyWrapper parent) { + return getPrismContext().itemFactory().createPropertyValue(); } + @Override + protected void refreshPanel(AjaxRequestTarget target) { + + } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/ExpressionPropertyPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismPropertyPanel.html similarity index 50% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/ExpressionPropertyPanel.html rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismPropertyPanel.html index c6ffa918cec..06b9580cf95 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/component/ExpressionPropertyPanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismPropertyPanel.html @@ -8,13 +8,12 @@ -
-
-
-
-
-
- +
+
+
+
+
+
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismPropertyPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismPropertyPanel.java new file mode 100644 index 00000000000..ae8ed7af1b1 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismPropertyPanel.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.gui.impl.prism.panel; + +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismPropertyValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; + +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; + +/** + * @author katkav + */ +public class PrismPropertyPanel extends ItemPanel, PrismPropertyWrapper> { + + private static final long serialVersionUID = 1L; + private static final Trace LOGGER = TraceManager.getTrace(PrismPropertyPanel.class); + + private static final String ID_HEADER = "header"; + + /** + * @param id + * @param model + */ + public PrismPropertyPanel(String id, IModel> model, ItemPanelSettings settings) { + super(id, model, settings); + } + + @Override + protected Panel createHeaderPanel() { + return new PrismPropertyHeaderPanel(ID_HEADER, getModel()) { + @Override + protected void refreshPanel(AjaxRequestTarget target) { + target.add(PrismPropertyPanel.this); + } + }; + } + + + @Override + protected Component createValuePanel(ListItem> item) { + PrismPropertyValuePanel panel = new PrismPropertyValuePanel("value", item.getModel(), getSettings()) { + + @Override + protected void removeValue(PrismPropertyValueWrapper valueToRemove, AjaxRequestTarget target) throws SchemaException { + PrismPropertyPanel.this.removeValue(valueToRemove, target); + } + }; + item.add(panel); + return panel; + } + + + @Override + protected PV createNewValue(PrismPropertyWrapper itemWrapper) { + return (PV) getPrismContext().itemFactory().createPropertyValue(); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismPropertyValuePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismPropertyValuePanel.java new file mode 100644 index 00000000000..df83520838f --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismPropertyValuePanel.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.prism.panel; + +import com.evolveum.midpoint.gui.impl.error.ErrorPanel; +import com.evolveum.midpoint.gui.impl.factory.panel.ItemPanelContext; +import com.evolveum.midpoint.gui.impl.factory.panel.PrismPropertyPanelContext; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismPropertyValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; + +import com.evolveum.midpoint.prism.PrismValue; + +import com.evolveum.midpoint.util.exception.SchemaException; + +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.model.IModel; + +public class PrismPropertyValuePanel extends PrismValuePanel, PrismPropertyValueWrapper> { + + + public PrismPropertyValuePanel(String id, IModel> model, ItemPanelSettings settings) { + super(id, model, settings); + } + + @Override + protected PC createPanelCtx(IModel> wrapper) { + PrismPropertyPanelContext panelCtx = new PrismPropertyPanelContext<>(wrapper); + return (PC) panelCtx; + } + + @Override + protected Component createDefaultPanel(String id) { + if (getPageBase().getApplication().usesDevelopmentConfig()) { + return new ErrorPanel(id, createStringResource("Cannot create component for: " + getModelObject().getParent().getItem())); + } else { + Label noComponent = new Label(id); + noComponent.setVisible(false); + return noComponent; + } + } + + @Override + protected PV createNewValue(PrismPropertyWrapper itemWrapper) { + return (PV) getPrismContext().itemFactory().createPropertyValue(); + } + + @Override + protected void removeValue(PrismPropertyValueWrapper valueToRemove, AjaxRequestTarget target) throws SchemaException { + throw new UnsupportedOperationException("Must be implemented in calling panel"); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismReferenceHeaderPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismReferenceHeaderPanel.java similarity index 73% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismReferenceHeaderPanel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismReferenceHeaderPanel.java index ebfcd7c546e..a16053ba444 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/PrismReferenceHeaderPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismReferenceHeaderPanel.java @@ -4,12 +4,14 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.impl.prism.panel; + +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismReferenceWrapper; import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.model.IModel; -import org.apache.wicket.model.LambdaModel; import com.evolveum.midpoint.prism.PrismReference; import com.evolveum.midpoint.prism.PrismReferenceDefinition; @@ -30,17 +32,19 @@ public PrismReferenceHeaderPanel(String id, IModel> mod @Override - protected void initButtons() { - // TODO Auto-generated method stub + protected Component createTitle(IModel label) { + Label displayName = new Label(ID_LABEL, label); + return displayName; } + @Override + protected PrismReferenceValue createNewValue(PrismReferenceWrapper parent) { + return getPrismContext().itemFactory().createReferenceValue(); + } @Override - protected Component createTitle(IModel label) { - Label displayName = new Label(ID_LABEL, label); + protected void refreshPanel(AjaxRequestTarget target) { - return displayName; } - } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismReferencePanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismReferencePanel.html new file mode 100644 index 00000000000..33cf00ca359 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismReferencePanel.html @@ -0,0 +1,30 @@ + + + + + +
+
+
+
+ + + + + + + + + +
+ + + +
+ + diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismReferencePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismReferencePanel.java new file mode 100644 index 00000000000..d2386a2ba50 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismReferencePanel.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.prism.panel; + +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismReferenceValueWrapperImpl; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismReferenceWrapper; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.util.exception.SchemaException; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; + +import com.evolveum.midpoint.prism.Referencable; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; + +/** + * @author katka + * + */ +public class PrismReferencePanel extends ItemPanel, PrismReferenceWrapper>{ + + private static final long serialVersionUID = 1L; + private static final Trace LOGGER = TraceManager.getTrace(PrismReferencePanel.class); + + private static final String ID_HEADER = "header"; + + public PrismReferencePanel(String id, IModel> model, ItemPanelSettings settings) { + super(id, model, settings); + } + + @Override + protected Panel createHeaderPanel() { + return new PrismReferenceHeaderPanel(ID_HEADER, getModel()) { + @Override + protected void refreshPanel(AjaxRequestTarget target) { + target.add(PrismReferencePanel.this); + } + }; + } + + @Override + protected Component createValuePanel(ListItem> item) { + PrismReferenceValuePanel valuePanel = new PrismReferenceValuePanel("value", item.getModel(), getSettings()) { + + @Override + protected void removeValue(PrismReferenceValueWrapperImpl valueToRemove, AjaxRequestTarget target) throws SchemaException { + PrismReferencePanel.this.removeValue(valueToRemove, target); + } + }; + item.add(valuePanel); + return valuePanel; + } + + @Override + public boolean isEnabled() { + if (getEditabilityHandler() != null && !getEditabilityHandler().isEditable(getModelObject())) { + return false; + } + return !getModelObject().isReadOnly() || isLink(getModelObject()); + } + + private boolean isLink(PrismReferenceWrapper iw){ + boolean isLink = false; + if (CollectionUtils.isNotEmpty(iw.getValues()) && iw.getValues().size() == 1) { + isLink = iw.getValues().get(0).isLink(); + } + return isLink; + } + + @Override + protected PV createNewValue(PrismReferenceWrapper itemWrapper) { + return (PV) getPrismContext().itemFactory().createReferenceValue(); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismReferenceValuePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismReferenceValuePanel.java new file mode 100644 index 00000000000..18dc6357486 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismReferenceValuePanel.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.prism.panel; + +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.gui.impl.factory.panel.ItemPanelContext; +import com.evolveum.midpoint.gui.impl.factory.panel.ItemRealValueModel; +import com.evolveum.midpoint.gui.impl.factory.panel.PrismReferencePanelContext; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismReferenceValueWrapperImpl; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismReferenceWrapper; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.prism.Referencable; + +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.web.component.form.ValueChoosePanel; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; + +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.model.IModel; +import org.apache.wicket.validation.INullAcceptingValidator; + +import javax.xml.namespace.QName; +import java.util.Arrays; +import java.util.List; + +public class PrismReferenceValuePanel extends PrismValuePanel, PrismReferenceValueWrapperImpl> { + + public PrismReferenceValuePanel(String id, IModel> model, ItemPanelSettings settings) { + super(id, model, settings); + } + + @Override + protected PC createPanelCtx(IModel> wrapper) { + PrismReferencePanelContext panelCtx = new PrismReferencePanelContext<>(wrapper); + return (PC) panelCtx; + } + + @Override + protected PV createNewValue(PrismReferenceWrapper itemWrapper) { + return (PV) getPrismContext().itemFactory().createReferenceValue(); + } + + @Override + protected Component createDefaultPanel(String id) { + ValueChoosePanel panel = new ValueChoosePanel(id, new ItemRealValueModel<>(getModel())) { + + private static final long serialVersionUID = 1L; + + @Override + protected ObjectFilter createCustomFilter() { + return getParentWrapper().getFilter(); + } + + @Override + protected boolean isEditButtonEnabled() { +// +// //TODO only is association +// return getModelObject() == null; + if (getModelObject() == null) { + return true; + } + return PrismReferenceValuePanel.this.getModelObject().isEditEnabled(); + + } + + @Override + protected void choosePerformed(AjaxRequestTarget target, O object) { + super.choosePerformed(target, object); + getBaseFormComponent().validate(); + target.add(getPageBase().getFeedbackPanel()); + target.add(getFeedback()); + } + + @Override + public List getSupportedTypes() { + List targetTypeList = getParentWrapper().getTargetTypes(); + if (targetTypeList == null || WebComponentUtil.isAllNulls(targetTypeList)) { + return Arrays.asList(ObjectType.COMPLEX_TYPE); + } + return targetTypeList; + } + + @Override + protected Class getDefaultType(List supportedTypes) { + if (AbstractRoleType.COMPLEX_TYPE.equals(getParentWrapper().getTargetTypeName())) { + return (Class) RoleType.class; + } else { + return super.getDefaultType(supportedTypes); + } + } + + }; + + panel.getBaseFormComponent().add((INullAcceptingValidator) createExpressionValidator()); + return panel; + } + + + private PrismReferenceWrapper getParentWrapper() { + return getModelObject().getParent(); + } + + @Override + protected void removeValue(PrismReferenceValueWrapperImpl valueToRemove, AjaxRequestTarget target) throws SchemaException { + throw new UnsupportedOperationException("Must be implemented in calling panel"); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismValuePanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismValuePanel.html new file mode 100644 index 00000000000..a20d1661df2 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismValuePanel.html @@ -0,0 +1,32 @@ + + + + + +
+
+
+
+
+ +
+
+ +
+ + + + + +
+
+ + + + diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismValuePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismValuePanel.java new file mode 100644 index 00000000000..8979e498c5a --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/PrismValuePanel.java @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.impl.prism.panel; + +import com.evolveum.midpoint.gui.api.component.BasePanel; +import com.evolveum.midpoint.gui.api.factory.GuiComponentFactory; +import com.evolveum.midpoint.gui.api.prism.wrapper.*; +import com.evolveum.midpoint.gui.impl.factory.panel.ItemPanelContext; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismValue; + +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.LoggingUtils; +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.message.FeedbackAlerts; +import com.evolveum.midpoint.web.component.util.VisibleBehaviour; + +import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; +import com.evolveum.midpoint.web.util.ExpressionValidator; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; + +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxEventBehavior; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; +import org.apache.wicket.ajax.markup.html.AjaxLink; +import org.apache.wicket.feedback.ComponentFeedbackMessageFilter; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.LambdaModel; +import org.apache.wicket.model.PropertyModel; + +public abstract class PrismValuePanel> extends BasePanel { + + private static final transient Trace LOGGER = TraceManager.getTrace(PrismValuePanel.class); + + private static final String ID_VALUE_FORM = "valueForm"; + private static final String ID_REMOVE_BUTTON = "removeButton"; + + private static final String ID_FEEDBACK = "feedback"; + private static final String ID_VALUE_CONTAINER = "valueContainer"; + + private static final String ID_HEADER_CONTAINER = "header"; + + private static final String ID_INPUT = "input"; + + private ItemPanelSettings settings; + + public PrismValuePanel(String id, IModel model, ItemPanelSettings settings) { + super(id, model); + this.settings = settings; + } + + @Override + protected void onInitialize() { + super.onInitialize(); + initLayout(); + setOutputMarkupId(true); + } + + private void initLayout() { + Form form = new Form<>(ID_VALUE_FORM); + add(form); + form.add(createHeaderPanel()); + + createValuePanel(form); + } + + private WebMarkupContainer createHeaderPanel() { + + WebMarkupContainer buttonContainer = new WebMarkupContainer(ID_HEADER_CONTAINER); + + AjaxLink removeButton = new AjaxLink(ID_REMOVE_BUTTON) { + private static final long serialVersionUID = 1L; + + @Override + public void onClick(AjaxRequestTarget target) { + try { + removeValue(PrismValuePanel.this.getModelObject(), target); + } catch (SchemaException e) { + LOGGER.error("Cannot remove value: {}", getModelObject()); + getSession().error("Cannot remove value "+ getModelObject()); + target.add(getPageBase().getFeedbackPanel()); + } + } + }; + removeButton.add(new VisibleBehaviour(() -> isRemoveButtonVisible())); + buttonContainer.add(removeButton); + + addToHeader(buttonContainer); + return buttonContainer; + } + + protected void addToHeader(WebMarkupContainer headerContainer) { + + } + + private WebMarkupContainer createValuePanel(Form form) { + + GuiComponentFactory factory = getPageBase().getRegistry().findValuePanelFactory(getModelObject().getParent()); + WebMarkupContainer valueContainer = new WebMarkupContainer(ID_VALUE_CONTAINER); + valueContainer.setOutputMarkupId(true); + form.add(valueContainer); + + // feedback + FeedbackAlerts feedback = new FeedbackAlerts(ID_FEEDBACK); + + feedback.setOutputMarkupId(true); + + if (factory == null) { + Component defaultPanel = createDefaultPanel(ID_INPUT); + valueContainer.add(defaultPanel); + feedback.setFilter(new ComponentFeedbackMessageFilter(defaultPanel)); + valueContainer.add(feedback); + return valueContainer; + } + + ItemPanelContext> panelCtx = createPanelCtx(new PropertyModel<>(getModel(), "parent")); + panelCtx.setComponentId(ID_INPUT); + panelCtx.setForm(getForm()); + panelCtx.setRealValueModel(getModel()); + panelCtx.setParentComponent(this); + panelCtx.setAjaxEventBehavior(createEventBehavior()); + panelCtx.setMandatoryHandler(getMandatoryHandler()); + panelCtx.setVisibleEnableBehaviour(createVisibleEnableBehavior()); + panelCtx.setExpressionValidator(createExpressionValidator()); + panelCtx.setFeedback(feedback); + + Panel component; + try { + component = factory.createPanel(panelCtx); + valueContainer.add(component); + factory.configure(panelCtx, component); + valueContainer.add(feedback); + + } catch (Throwable e) { + LoggingUtils.logUnexpectedException(LOGGER, "Cannot create panel", e); + getSession().error("Cannot create panel"); + throw new RuntimeException(e); + } + + return valueContainer; + + } + + private AjaxEventBehavior createEventBehavior() { + return new AjaxFormComponentUpdatingBehavior("change") { + + private static final long serialVersionUID = 1L; + + @Override + protected void onUpdate(AjaxRequestTarget target) { + target.add(getPageBase().getFeedbackPanel()); + target.add(getFeedback()); + } + + @Override + protected void onError(AjaxRequestTarget target, RuntimeException e) { + target.add(getPageBase().getFeedbackPanel()); + target.add(getFeedback()); + } + + }; + } + + private VisibleEnableBehaviour createVisibleEnableBehavior() { + return new VisibleEnableBehaviour() { + +// @Override +// public boolean isVisible() { +// return isVisibleValue(); +// } + + @Override + public boolean isEnabled() { + if (getEditabilityHandler() != null) { + return getEditabilityHandler().isEditable(getModelObject().getParent()); + } + return super.isEnabled(); + } + }; + } + + protected ItemPanelSettings getSettings() { + return settings; + } + + protected ItemMandatoryHandler getMandatoryHandler() { + if (settings == null) { + return null; + } + + return settings.getMandatoryHandler(); + } + + protected ItemEditabilityHandler getEditabilityHandler() { + if (settings == null) { + return null; + } + + return settings.getEditabilityHandler(); + } + + protected ItemVisibilityHandler getVisibilityHandler() { + if (settings == null) { + return null; + } + + return settings.getVisibilityHandler(); + } + + protected ExpressionValidator createExpressionValidator() { + return new ExpressionValidator( + LambdaModel.of(getModelObject().getParent()::getFormComponentValidator), getPageBase()) { + + @Override + protected O getObjectType() { + return getObject(); + } + }; + } + + protected abstract PC createPanelCtx(IModel wrapper); + + private O getObject() { + + PrismObjectWrapper objectWrapper = getModelObject().getParent().findObjectWrapper(); + if (objectWrapper == null) { + return null; + } + + try { + PrismObject objectNew = objectWrapper.getObjectApplyDelta(); + return objectNew.asObjectable(); + } catch (SchemaException e) { + LOGGER.error("Cannot apply deltas to object for validation: {}", e.getMessage(), e); + return null; + } + } + + protected abstract Component createDefaultPanel(String id); + + protected abstract PV createNewValue(IW itemWrapper); + + //TODO move to the ItemPanel, exception handling + protected abstract void removeValue(VW valueToRemove, AjaxRequestTarget target) throws SchemaException; + + + protected boolean isRemoveButtonVisible() { + return !getModelObject().getParent().isReadOnly(); + + } + + private Form getForm() { + return (Form) get(ID_VALUE_FORM); + } + + protected FeedbackAlerts getFeedback() { + return (FeedbackAlerts) get(createComponentPath(ID_VALUE_FORM, ID_VALUE_CONTAINER, ID_FEEDBACK)); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ProfilingClassLoggerPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ProfilingClassLoggerPanel.java similarity index 81% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ProfilingClassLoggerPanel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ProfilingClassLoggerPanel.java index 497b17ee658..9b7e784ee64 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ProfilingClassLoggerPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ProfilingClassLoggerPanel.java @@ -4,12 +4,14 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.impl.prism.panel; + +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemVisibilityHandler; import org.apache.wicket.model.IModel; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; import com.evolveum.midpoint.web.component.prism.ItemVisibility; import com.evolveum.midpoint.xml.ns._public.common.common_3.ClassLoggerConfigurationType; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ResourceAttributeDefinitionHeaderPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ResourceAttributeDefinitionHeaderPanel.html similarity index 100% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ResourceAttributeDefinitionHeaderPanel.html rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ResourceAttributeDefinitionHeaderPanel.html diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ResourceAttributeDefinitionHeaderPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ResourceAttributeDefinitionHeaderPanel.java similarity index 92% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ResourceAttributeDefinitionHeaderPanel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ResourceAttributeDefinitionHeaderPanel.java index f299177f66e..09710f9d190 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ResourceAttributeDefinitionHeaderPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ResourceAttributeDefinitionHeaderPanel.java @@ -4,13 +4,13 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.impl.prism.panel; +import com.evolveum.midpoint.gui.api.prism.wrapper.ResourceAttributeWrapper; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.model.IModel; import com.evolveum.midpoint.web.component.util.VisibleBehaviour; -import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; /** * @author skublik diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ResourceAttributeDefinitionPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ResourceAttributeDefinitionPanel.java similarity index 81% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ResourceAttributeDefinitionPanel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ResourceAttributeDefinitionPanel.java index 60df4547b52..7f5bb5ea8d7 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ResourceAttributeDefinitionPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ResourceAttributeDefinitionPanel.java @@ -5,8 +5,9 @@ * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.impl.prism.panel; +import com.evolveum.midpoint.gui.api.prism.wrapper.ResourceAttributeWrapper; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.IModel; @@ -23,12 +24,6 @@ public class ResourceAttributeDefinitionPanel extends PrismPropertyPanel { private static final String ID_HEADER = "header"; - private static final String ID_FEEDBACK = "feedback"; - private static final String ID_VALUE_CONTAINER = "valueContainer"; - - private static final String ID_FORM = "form"; - private static final String ID_INPUT = "input"; - /** * @param id diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ShadowPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ShadowPanel.html new file mode 100644 index 00000000000..27d68996964 --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ShadowPanel.html @@ -0,0 +1,32 @@ + + + + + +
+
+
+
+ +
+
+
+ + +
+
+
+ + +
+
+
+ +
+ + diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ShadowPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ShadowPanel.java similarity index 87% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ShadowPanel.java rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ShadowPanel.java index f3bce78375f..75c08c2513d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/ShadowPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/ShadowPanel.java @@ -4,14 +4,14 @@ * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ -package com.evolveum.midpoint.gui.impl.prism; +package com.evolveum.midpoint.gui.impl.prism.panel; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.IModel; import com.evolveum.midpoint.gui.api.component.BasePanel; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.ShadowWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ShadowWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.util.exception.SchemaException; @@ -37,14 +37,10 @@ public class ShadowPanel extends BasePanel { private static final Trace LOGGER = TraceManager.getTrace(ShadowPanel.class); - protected static final String ID_SHADOWS_CONTAINER = "shadowContainer"; - - private static final String ID_ATTRIBUTES = "attributes"; private static final String ID_ASSOCIATIONS = "associations"; private static final String ID_ACTIVATION = "activation"; private static final String ID_PASSWORD = "password"; - private static final String ID_ERROR = "error"; public ShadowPanel(String id, IModel model) { @@ -70,8 +66,7 @@ private void initLayout() { add(attributesPanel); ItemPanelSettingsBuilder associationBuilder = new ItemPanelSettingsBuilder() - .visibilityHandler(itemWrapper -> checkShadowContainerVisibility(itemWrapper, getModel())) - .showOnTopLevel(true); + .visibilityHandler(itemWrapper -> checkShadowContainerVisibility(itemWrapper, getModel())); Panel associationsPanel = getPageBase().initItemPanel(ID_ASSOCIATIONS, ShadowAssociationType.COMPLEX_TYPE, PrismContainerWrapperModel.fromContainerWrapper(getModel(), ShadowType.F_ASSOCIATION), associationBuilder.build()); associationsPanel.add(new VisibleBehaviour(() -> checkAssociationsVisibility())); @@ -79,16 +74,14 @@ private void initLayout() { ItemPanelSettingsBuilder activationBuilder = new ItemPanelSettingsBuilder() - .visibilityHandler(itemWrapper -> checkShadowContainerVisibility(itemWrapper, getModel())) - .showOnTopLevel(true); + .visibilityHandler(itemWrapper -> checkShadowContainerVisibility(itemWrapper, getModel())); Panel activationPanel = getPageBase().initItemPanel(ID_ACTIVATION, ActivationType.COMPLEX_TYPE, PrismContainerWrapperModel.fromContainerWrapper(getModel(), ShadowType.F_ACTIVATION), activationBuilder.build()); activationPanel.add(new VisibleBehaviour(() -> isActivationSupported())); add(activationPanel); ItemPanelSettingsBuilder passwordSettingsBuilder = new ItemPanelSettingsBuilder() - .visibilityHandler(itemWrapper -> checkShadowContainerVisibility(itemWrapper, getModel())) - .showOnTopLevel(true); + .visibilityHandler(itemWrapper -> checkShadowContainerVisibility(itemWrapper, getModel())); Panel passwordPanel = getPageBase().initItemPanel(ID_PASSWORD, PasswordType.COMPLEX_TYPE, PrismContainerWrapperModel.fromContainerWrapper(getModel(), ItemPath.create(ShadowType.F_CREDENTIALS, CredentialsType.F_PASSWORD)), passwordSettingsBuilder.build()); passwordPanel.add(new VisibleBehaviour(() -> isCredentialsSupported())); @@ -96,8 +89,7 @@ private void initLayout() { } catch (SchemaException e) { getSession().error("Cannot create panels for shadow, reason: " + e.getMessage()); LOGGER.error("Cannot create panels for shadow, reason: {}", e.getMessage(), e); -// ErrorPanel errorPanel = new ErrorPanel(ID_ERROR, createStringResource("Error creatinf shadow panels")); -// specificContainers.add(errorPanel); + } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/ContainerOfSystemConfigurationPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/SingleContainerPanel.html similarity index 62% rename from gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/ContainerOfSystemConfigurationPanel.html rename to gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/SingleContainerPanel.html index 01dd3635505..f1e40232d0d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/configuration/component/ContainerOfSystemConfigurationPanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/prism/panel/SingleContainerPanel.html @@ -1,5 +1,5 @@ + + +
+ +

+

+ + diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/dialog/SelectExportingColumnsPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/dialog/SelectExportingColumnsPanel.java new file mode 100644 index 00000000000..a97c0d141cf --- /dev/null +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/dialog/SelectExportingColumnsPanel.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2010-2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.web.component.dialog; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxRequestTarget; +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.DataTable; +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; +import org.apache.wicket.extensions.markup.html.repeater.data.table.export.IExportableColumn; +import org.apache.wicket.markup.html.WebMarkupContainer; +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 org.apache.wicket.model.StringResourceModel; + +import com.evolveum.midpoint.gui.api.component.BasePanel; +import com.evolveum.midpoint.gui.api.component.result.MessagePanel; +import com.evolveum.midpoint.gui.api.page.PageBase; +import com.evolveum.midpoint.web.component.AjaxButton; +import com.evolveum.midpoint.web.component.data.BoxedTablePanel; +import com.evolveum.midpoint.web.component.data.column.CheckBoxHeaderColumn; +import com.evolveum.midpoint.web.component.util.SelectableBean; +import com.evolveum.midpoint.web.component.util.SelectableListDataProvider; +import com.evolveum.midpoint.web.component.util.VisibleBehaviour; + +/** + * @author lskublik + */ +public class SelectExportingColumnsPanel extends BasePanel implements Popupable { + + private static final long serialVersionUID = 1L; + private static final String ID_PANEL = "panel"; + private static final String ID_WARNING_MESSAGE = "warningMessage"; + private static final String ID_EXPORT_ALL = "exportAll"; + private static final String ID_EXPORT_SELECTED = "exportSelected"; + private static final String ID_CANCEL = "cancelButton"; + private static final String ID_TABLE = "table"; + + private DataTable dataTable; + private List exportedColumnsIndex; + private Long exportSizeLimit; + + public SelectExportingColumnsPanel(String id, DataTable dataTable, List exportedColumnsIndex) { + this(id, dataTable, exportedColumnsIndex, null); + } + + public SelectExportingColumnsPanel(String id, DataTable dataTable, List exportedColumnsIndex, + Long exportSizeLimit) { + super(id); + this.dataTable = dataTable; + this.exportedColumnsIndex = exportedColumnsIndex; + this.exportSizeLimit = exportSizeLimit; + } + + @Override + protected void onInitialize() { + super.onInitialize(); + initLayout(dataTable, exportedColumnsIndex, exportSizeLimit); + } + + private void initLayout(DataTable dataTable, List exportedColumnsIndex, Long exportSizeLimit) { + WebMarkupContainer panel = new WebMarkupContainer(ID_PANEL); + + MessagePanel warningMessage = new MessagePanel(ID_WARNING_MESSAGE, MessagePanel.MessagePanelType.WARN, getWarningMessageModel()); + warningMessage.setOutputMarkupId(true); + warningMessage.add(new VisibleBehaviour(() -> getWarningMessageModel() != null)); + panel.add(warningMessage); + + BoxedTablePanel> table = createTable(dataTable); + panel.add(table); + + AjaxButton exportAll = new AjaxButton(ID_EXPORT_ALL, + new StringResourceModel("SelectExportingColumnsPanel.exportAll", this, null)) { + + private static final long serialVersionUID = 1L; + + @Override + public void onClick(AjaxRequestTarget target) { + List availableData = ((SelectableListDataProvider) table.getDataTable().getDataProvider()).getAvailableData(); + exportedColumnsIndex.addAll(availableData); + ((PageBase) getPage()).hideMainPopup(target); + exportPerformed(target); + } + }; + panel.add(exportAll); + AjaxButton exportSelected = new AjaxButton(ID_EXPORT_SELECTED, + new StringResourceModel("SelectExportingColumnsPanel.exportSelected", this, null)) { + + private static final long serialVersionUID = 1L; + + @Override + public void onClick(AjaxRequestTarget target) { + List availableData = ((SelectableListDataProvider) table.getDataTable().getDataProvider()).getSelectedObjects(); + exportedColumnsIndex.addAll(availableData); + ((PageBase) getPage()).hideMainPopup(target); + exportPerformed(target); + } + }; + panel.add(exportSelected); + + AjaxButton cancelButton = new AjaxButton(ID_CANCEL, + new StringResourceModel("Button.cancel", this, null)) { + private static final long serialVersionUID = 1L; + + @Override + public void onClick(AjaxRequestTarget target) { + cancelPerformed(target); + } + }; + panel.add(cancelButton); + add(panel); + } + + private IModel getWarningMessageModel() { + if (exportSizeLimit != null) { + return getPageBase().createStringResource("CsvDownloadButtonPanel.confirmationMessage", exportSizeLimit); + } + return null; + } + + public void exportPerformed(AjaxRequestTarget target) { + + } + + public void cancelPerformed(AjaxRequestTarget target) { + ((PageBase) getPage()).hideMainPopup(target); + } + + private BoxedTablePanel> createTable(DataTable dataTable) { + + List> allColumns = dataTable.getColumns(); + List exportableColumnIndex = getExportableColumns(dataTable); + if (exportableColumnIndex.isEmpty()) { + throw new IllegalArgumentException("List of exportable columns is empty"); + } + + List, String>> columns = new ArrayList<>(); + CheckBoxHeaderColumn> checkboxColumn = new CheckBoxHeaderColumn<>(); + columns.add(checkboxColumn); + StringResourceModel nameString = getPageBase().createStringResource("SelectExportingColumnsPanel.nameColumn"); + IColumn, String> nameColumn = new AbstractColumn, String>(nameString) { + + @Override + public void populateItem(Item>> cellItem, String componentId, + IModel> rowModel) { + IModel stringModel = ((IExportableColumn)allColumns.get(rowModel.getObject().getValue())).getDisplayModel(); + cellItem.add(new Label(componentId, stringModel)); + } + }; + columns.add(nameColumn); + + SelectableListDataProvider, Integer> provider = + new SelectableListDataProvider, Integer>(getPageBase(), Model.ofList(exportableColumnIndex)); + + BoxedTablePanel> table = + new BoxedTablePanel>(ID_TABLE, provider, columns, null, 20) { + private static final long serialVersionUID = 1L; + + @Override + protected WebMarkupContainer createHeader(String headerId) { + return new WebMarkupContainer(headerId); + } + + @Override + public String getAdditionalBoxCssClasses() { + return null; + } + + @Override + protected WebMarkupContainer createButtonToolbar(String id) { + return new WebMarkupContainer(id); + } + + @Override + protected boolean hideFooterIfSinglePage(){ + return true; + } + + @Override + public int getAutoRefreshInterval() { + return 0; + } + + @Override + public boolean isAutoRefreshEnabled() { + return false; + } + }; + table.setOutputMarkupId(true); + + return table; + } + + private List getExportableColumns(DataTable dataTable) { + List> columns = dataTable.getColumns(); + List exportableColumn = new ArrayList<>(); + for (IColumn column : columns) { + if (column instanceof IExportableColumn) { + exportableColumn.add(columns.indexOf(column)); + } + } + return exportableColumn; + } + + @Override + public int getWidth() { + return 500; + } + + @Override + public int getHeight() { + int rows = getExportableColumns(dataTable).size(); + int message = 0; + if (exportSizeLimit != null) { + message = 60; + } + int height = (rows * 40) + 130 + message; + return height > 500 ? 500 : height; + } + + @Override + public String getWidthUnit(){ + return "px"; + } + + @Override + public String getHeightUnit(){ + return "px"; + } + + @Override + public StringResourceModel getTitle() { + return new StringResourceModel("SelectExportingColumnsPanel.title"); + } + + @Override + public Component getComponent() { + return this; + } + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/AssociationExpressionValuePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/AssociationExpressionValuePanel.java index a81113d1d16..a83a4c6361e 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/AssociationExpressionValuePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/AssociationExpressionValuePanel.java @@ -9,46 +9,27 @@ import com.evolveum.midpoint.gui.api.component.BasePanel; import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.impl.prism.PrismReferencePanel; -import com.evolveum.midpoint.prism.PrismReferenceValue; import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.prism.query.QueryFactory; -import com.evolveum.midpoint.prism.xnode.MapXNode; import com.evolveum.midpoint.schema.SchemaConstantsGenerated; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.AjaxButton; -import com.evolveum.midpoint.web.component.data.DoubleButtonPanel; -import com.evolveum.midpoint.web.component.form.ValueChoosePanel; -import com.evolveum.midpoint.web.component.form.multivalue.MultiValueChoosePanel; import com.evolveum.midpoint.web.component.form.multivalue.MultiValueObjectChoosePanel; -import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItem; -import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItemAction; -import com.evolveum.midpoint.web.component.util.EnableBehaviour; -import com.evolveum.midpoint.web.component.util.VisibleBehaviour; import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; -import com.evolveum.midpoint.web.page.admin.configuration.component.ChooseTypePanel; import com.evolveum.midpoint.web.page.admin.configuration.component.EmptyOnChangeAjaxFormUpdatingBehavior; import com.evolveum.midpoint.web.util.ExpressionUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang.StringUtils; import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.ajax.markup.html.AjaxLink; -import org.apache.wicket.behavior.AttributeAppender; import org.apache.wicket.feedback.FeedbackMessage; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.panel.FeedbackPanel; -import org.apache.wicket.markup.repeater.RepeatingView; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import javax.xml.namespace.QName; import java.util.ArrayList; import java.util.Arrays; -import java.util.Iterator; import java.util.List; /** diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractFocusTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractFocusTabPanel.java index f892aacf662..b2a00caad54 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractFocusTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractFocusTabPanel.java @@ -9,8 +9,8 @@ import java.util.List; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.api.prism.ShadowWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ShadowWrapper; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.component.form.Form; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractObjectMainPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractObjectMainPanel.java index 09e5ae9a1fe..25519f585d8 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractObjectMainPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractObjectMainPanel.java @@ -17,7 +17,7 @@ import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.security.api.AuthorizationConstants; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractObjectTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractObjectTabPanel.java index ee97d1f6e5d..fb33a597583 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractObjectTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractObjectTabPanel.java @@ -1,126 +1,128 @@ -/* - * Copyright (c) 2010-2017 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.component.objectdetails; - -import javax.xml.namespace.QName; - -import org.apache.commons.lang.StringUtils; -import org.apache.wicket.MarkupContainer; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.markup.html.panel.Panel; -import org.apache.wicket.model.StringResourceModel; -import org.apache.wicket.request.mapper.parameter.PageParameters; - -import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.impl.prism.ItemPanelSettingsBuilder; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.dialog.Popupable; -import com.evolveum.midpoint.web.component.form.Form; -import com.evolveum.midpoint.web.component.prism.ItemVisibility; -import com.evolveum.midpoint.web.model.PrismPropertyWrapperModel; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; - -/** - * @author semancik - */ -public abstract class AbstractObjectTabPanel extends Panel { - private static final long serialVersionUID = 1L; - - protected static final String ID_MAIN_FORM = "mainForm"; - - private static final Trace LOGGER = TraceManager.getTrace(AbstractObjectTabPanel.class); - - private LoadableModel> objectWrapperModel; - private Form> mainForm; - - public AbstractObjectTabPanel(String id, Form> mainForm, LoadableModel> objectWrapperModel) { - super(id); - this.objectWrapperModel = objectWrapperModel; - this.mainForm = mainForm; - } - - public LoadableModel> getObjectWrapperModel() { - return objectWrapperModel; - } - - public PrismObjectWrapper getObjectWrapper() { - return objectWrapperModel.getObject(); - } - - protected PrismContext getPrismContext() { - return getPageBase().getPrismContext(); - } - - protected PageParameters getPageParameters() { - return getPageBase().getPageParameters(); - } - - public PageBase getPageBase() { - return (PageBase) getPage(); - } - - public Form> getMainForm() { - return mainForm; - } - - public StringResourceModel createStringResource(String resourceKey, Object... objects) { - return PageBase.createStringResourceStatic(this, resourceKey, objects); -// return new StringResourceModel(resourceKey, this, null, resourceKey, objects); - } - - public String getString(String resourceKey, Object... objects) { - return createStringResource(resourceKey, objects).getString(); - } - - protected String createComponentPath(String... components) { - return StringUtils.join(components, ":"); - } - - protected void showResult(OperationResult result) { - getPageBase().showResult(result); - } - - protected void showResult(OperationResult result, boolean showSuccess) { - getPageBase().showResult(result, showSuccess); - } - - - protected WebMarkupContainer getFeedbackPanel() { - return getPageBase().getFeedbackPanel(); - } - - protected void showModalWindow(Popupable popupable, AjaxRequestTarget target) { - getPageBase().showMainPopup(popupable, target); - target.add(getFeedbackPanel()); - } - - protected Panel addPrismPropertyPanel(MarkupContainer parentComponent, String id, QName typeName, ItemPath propertyPath) { - - try { - //FIXME : really always visible? - ItemPanelSettingsBuilder settingsBuilder = new ItemPanelSettingsBuilder(); - settingsBuilder.visibilityHandler(wrapper -> ItemVisibility.VISIBLE); - - Panel panel = getPageBase().initItemPanel(id, typeName, PrismPropertyWrapperModel.fromContainerWrapper(getObjectWrapperModel(), propertyPath), settingsBuilder.build()); - parentComponent.add(panel); - return panel; - } catch (SchemaException e) { - LOGGER.error("Cannot create panel for {}", typeName, e); - getSession().error("Cannot create panel for " + typeName + ", reason: " + e.getMessage()); - } - - return null; - } -} +/* + * Copyright (c) 2010-2017 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.component.objectdetails; + +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.gui.impl.prism.panel.ItemHeaderPanel; + +import com.evolveum.midpoint.gui.impl.prism.panel.ItemPanelSettingsBuilder; + +import org.apache.commons.lang.StringUtils; +import org.apache.wicket.MarkupContainer; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.StringResourceModel; +import org.apache.wicket.request.mapper.parameter.PageParameters; + +import com.evolveum.midpoint.gui.api.model.LoadableModel; +import com.evolveum.midpoint.gui.api.page.PageBase; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.component.dialog.Popupable; +import com.evolveum.midpoint.web.component.form.Form; +import com.evolveum.midpoint.web.component.prism.ItemVisibility; +import com.evolveum.midpoint.web.model.PrismPropertyWrapperModel; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; + +/** + * @author semancik + */ +public abstract class AbstractObjectTabPanel extends Panel { + private static final long serialVersionUID = 1L; + + protected static final String ID_MAIN_FORM = "mainForm"; + + private static final Trace LOGGER = TraceManager.getTrace(AbstractObjectTabPanel.class); + + private LoadableModel> objectWrapperModel; + private Form> mainForm; + + public AbstractObjectTabPanel(String id, Form> mainForm, LoadableModel> objectWrapperModel) { + super(id); + this.objectWrapperModel = objectWrapperModel; + this.mainForm = mainForm; + } + + public LoadableModel> getObjectWrapperModel() { + return objectWrapperModel; + } + + public PrismObjectWrapper getObjectWrapper() { + return objectWrapperModel.getObject(); + } + + protected PrismContext getPrismContext() { + return getPageBase().getPrismContext(); + } + + protected PageParameters getPageParameters() { + return getPageBase().getPageParameters(); + } + + public PageBase getPageBase() { + return (PageBase) getPage(); + } + + public Form> getMainForm() { + return mainForm; + } + + public StringResourceModel createStringResource(String resourceKey, Object... objects) { + return PageBase.createStringResourceStatic(this, resourceKey, objects); +// return new StringResourceModel(resourceKey, this, null, resourceKey, objects); + } + + public String getString(String resourceKey, Object... objects) { + return createStringResource(resourceKey, objects).getString(); + } + + protected String createComponentPath(String... components) { + return StringUtils.join(components, ":"); + } + + protected void showResult(OperationResult result) { + getPageBase().showResult(result); + } + + protected void showResult(OperationResult result, boolean showSuccess) { + getPageBase().showResult(result, showSuccess); + } + + + protected WebMarkupContainer getFeedbackPanel() { + return getPageBase().getFeedbackPanel(); + } + + protected void showModalWindow(Popupable popupable, AjaxRequestTarget target) { + getPageBase().showMainPopup(popupable, target); + target.add(getFeedbackPanel()); + } + + protected Panel addPrismPropertyPanel(MarkupContainer parentComponent, String id, QName typeName, ItemPath propertyPath) { + + try { + ItemPanelSettingsBuilder settingsBuilder = new ItemPanelSettingsBuilder(); + settingsBuilder.visibilityHandler(wrapper -> ItemVisibility.AUTO); + + Panel panel = getPageBase().initItemPanel(id, typeName, PrismPropertyWrapperModel.fromContainerWrapper(getObjectWrapperModel(), propertyPath), settingsBuilder.build()); + parentComponent.add(panel); + return panel; + } catch (SchemaException e) { + LOGGER.error("Cannot create panel for {}", typeName, e); + getSession().error("Cannot create panel for " + typeName + ", reason: " + e.getMessage()); + } + + return null; + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractRoleInducementPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractRoleInducementPanel.java index e0fa1579b49..d81871c3eae 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractRoleInducementPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractRoleInducementPanel.java @@ -9,7 +9,7 @@ import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.web.component.assignment.InducementsPanel; import com.evolveum.midpoint.web.component.form.Form; import com.evolveum.midpoint.web.model.PrismContainerWrapperModel; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractRoleMainPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractRoleMainPanel.java index b18ede050d8..071c4de80ea 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractRoleMainPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AbstractRoleMainPanel.java @@ -1,326 +1,326 @@ -/* - * Copyright (c) 2015-2016 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.component.objectdetails; - -import java.util.List; -import java.util.Map; - -import javax.xml.namespace.QName; - -import org.apache.wicket.ajax.AjaxChannel; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.ajax.attributes.AjaxRequestAttributes; -import org.apache.wicket.behavior.AttributeAppender; -import org.apache.wicket.extensions.markup.html.tabs.ITab; -import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.model.Model; - -import com.evolveum.midpoint.gui.api.ComponentConstants; -import com.evolveum.midpoint.gui.api.component.tabs.CountablePanelTab; -import com.evolveum.midpoint.gui.api.component.tabs.PanelTab; -import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.api.prism.ShadowWrapper; -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.LoggingUtils; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.AjaxButton; -import com.evolveum.midpoint.web.component.assignment.AssignmentEditorDto; -import com.evolveum.midpoint.web.component.assignment.AssignmentsUtil; -import com.evolveum.midpoint.web.component.assignment.SwitchAssignmentTypePanel; -import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; -import com.evolveum.midpoint.web.model.PrismContainerWrapperModel; -import com.evolveum.midpoint.web.page.admin.PageAdminFocus; -import com.evolveum.midpoint.web.page.admin.PageAdminObjectDetails; -import com.evolveum.midpoint.web.page.admin.roles.AbstractRoleMemberPanel; -import com.evolveum.midpoint.web.page.admin.roles.AvailableRelationDto; -import com.evolveum.midpoint.web.page.admin.users.dto.UserDtoStatus; -import com.evolveum.midpoint.web.page.self.PageAssignmentShoppingCart; -import com.evolveum.midpoint.web.security.GuiAuthorizationConstants; -import com.evolveum.midpoint.web.session.RoleCatalogStorage; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AreaCategoryType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ServiceType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; - -/** - * @author semancik - * - */ -public abstract class AbstractRoleMainPanel extends FocusMainPanel { - private static final long serialVersionUID = 1L; - - private static final Trace LOGGER = TraceManager.getTrace(AbstractRoleMainPanel.class); - - private static final String DOT_CLASS = AbstractRoleMainPanel.class.getName(); - private static final String OPERATION_CAN_SEARCH_ROLE_MEMBERSHIP_ITEM = DOT_CLASS + "canSearchRoleMembershipItem"; - private static final String OPERATION_LOAD_ASSIGNMENTS_LIMIT = DOT_CLASS + "loadAssignmentsLimit"; - private static final String ID_SHOPPING_CART_BUTTONS_PANEL = "shoppingCartButtonsPanel"; - private static final String ID_ADD_TO_CART_BUTTON = "addToCartButton"; - - public AbstractRoleMainPanel(String id, LoadableModel> objectModel, - LoadableModel> projectionModel, - PageAdminFocus parentPage) { - super(id, objectModel, projectionModel, parentPage); - } - - @Override - protected void initLayoutButtons(PageAdminObjectDetails parentPage) { - super.initLayoutButtons(parentPage); - initShoppingCartPanel(parentPage); - } - - private void initShoppingCartPanel(PageAdminObjectDetails parentPage){ - RoleCatalogStorage storage = parentPage.getSessionStorage().getRoleCatalog(); - - WebMarkupContainer shoppingCartButtonsPanel = new WebMarkupContainer(ID_SHOPPING_CART_BUTTONS_PANEL); - shoppingCartButtonsPanel.setOutputMarkupId(true); - shoppingCartButtonsPanel.add(new VisibleEnableBehaviour(){ - private static final long serialVersionUID = 1L; - - @Override - public boolean isVisible(){ - //show panel only in case if user came to object details from - // Role Catalog page - return PageAssignmentShoppingCart.class.equals(WebComponentUtil.getPreviousPageClass(parentPage)); - } - }); - getMainForm().add(shoppingCartButtonsPanel); - - AjaxButton addToCartButton = new AjaxButton(ID_ADD_TO_CART_BUTTON, parentPage - .createStringResource("PageAssignmentDetails.addToCartButton")) { - private static final long serialVersionUID = 1L; - - @Override - protected void updateAjaxAttributes(AjaxRequestAttributes attributes) { - attributes.setChannel(new AjaxChannel("blocking", AjaxChannel.Type.ACTIVE)); - } - - @Override - public void onClick(AjaxRequestTarget target) { - AssignmentEditorDto dto = AssignmentEditorDto.createDtoFromObject(getObject().asObjectable(), UserDtoStatus.ADD, parentPage); - storage.getAssignmentShoppingCart().add(dto); - parentPage.redirectBack(); - } - }; - addToCartButton.add(AttributeAppender.append("class", new LoadableModel() { - @Override - protected String load() { - return addToCartButton.isEnabled() ? "btn btn-success" : "btn btn-success disabled"; - } - })); - addToCartButton.setOutputMarkupId(true); - addToCartButton.add(new VisibleEnableBehaviour(){ - private static final long serialVersionUID = 1L; - - @Override - public boolean isEnabled(){ - int assignmentsLimit = AssignmentsUtil.loadAssignmentsLimit(new OperationResult(OPERATION_LOAD_ASSIGNMENTS_LIMIT), - parentPage); - AssignmentEditorDto dto = AssignmentEditorDto.createDtoFromObject(AbstractRoleMainPanel.this.getObject().asObjectable(), - UserDtoStatus.ADD, parentPage); - return !AssignmentsUtil.isShoppingCartAssignmentsLimitReached(assignmentsLimit, parentPage) - && (storage.isMultiUserRequest() || dto.isAssignable()); } - }); - addToCartButton.add(AttributeAppender.append("title", - AssignmentsUtil.getShoppingCartAssignmentsLimitReachedTitleModel(parentPage))); - shoppingCartButtonsPanel.add(addToCartButton); - } - - @Override - protected List createTabs(final PageAdminObjectDetails parentPage) { - List tabs = super.createTabs(parentPage); - - tabs.add( - new PanelTab(parentPage.createStringResource("pageAdminFocus.applicablePolicies"), - getTabVisibility( ComponentConstants.UI_FOCUS_TAB_APPLICABLE_POLICIES_URL, false, parentPage)) { - - private static final long serialVersionUID = 1L; - - @Override - public WebMarkupContainer createPanel(String panelId) { - return new FocusApplicablePoliciesTabPanel<>(panelId, getMainForm(), getObjectModel()); - } - }); - - tabs.add(new CountablePanelTab(parentPage.createStringResource("FocusType.inducement"), - getTabVisibility( ComponentConstants.UI_FOCUS_TAB_INDUCEMENTS_URL, false, parentPage)) { - - private static final long serialVersionUID = 1L; - - @Override - public WebMarkupContainer createPanel(String panelId) { - SwitchAssignmentTypePanel panel = new SwitchAssignmentTypePanel(panelId, - PrismContainerWrapperModel.fromContainerWrapper(getObjectModel(), AbstractRoleType.F_INDUCEMENT)){ - private static final long serialVersionUID = 1L; - - @Override - protected boolean isInducement(){ - return true; - } - }; - return panel; - } - - @Override - public String getCount(){ - return getInducementsCount(); - } - - }); - - tabs.add(new PanelTab(parentPage.createStringResource("pageRole.members"), - getTabVisibility( ComponentConstants.UI_FOCUS_TAB_MEMBERS_URL, false, parentPage)) { - - private static final long serialVersionUID = 1L; - - @Override - public WebMarkupContainer createPanel(String panelId) { - return createMemberPanel(panelId); - } - - @Override - public boolean isVisible() { - return super.isVisible() && - getObjectWrapper().getStatus() != ItemStatus.ADDED && - isAllowedToReadRoleMembership(getObjectWrapper().getOid(), parentPage); - } - }); - - tabs.add(new PanelTab(parentPage.createStringResource("pageRole.governance"), - getTabVisibility( ComponentConstants.UI_FOCUS_TAB_GOVERNANCE_URL, false, parentPage)) { - - private static final long serialVersionUID = 1L; - - @Override - public WebMarkupContainer createPanel(String panelId) { - return createGovernancePanel(panelId); - } - - @Override - public boolean isVisible() { - return super.isVisible() && getObjectWrapper().getStatus() != ItemStatus.ADDED; - } - }); - - return tabs; - } - - - public AbstractRoleMemberPanel createMemberPanel(String panelId) { - - return new AbstractRoleMemberPanel(panelId, new Model<>(getObject().asObjectable())) { - - private static final long serialVersionUID = 1L; - - @Override - protected AvailableRelationDto getSupportedRelations() { - return getSupportedMembersTabRelations(); - } - - }; - } - - - public AbstractRoleMemberPanel createGovernancePanel(String panelId) { - - return new AbstractRoleMemberPanel(panelId, new Model<>(getObject().asObjectable())) { - - private static final long serialVersionUID = 1L; - - @Override - protected AvailableRelationDto getSupportedRelations() { - AvailableRelationDto avariableRelations = getSupportedGovernanceTabRelations(); - avariableRelations.setDefaultRelation(getDefaultGovernanceRelation()); - return avariableRelations; - } - - @Override - protected Map getAuthorizations(QName complexType) { - return getGovernanceTabAuthorizations(); - } - - }; - } - - protected AvailableRelationDto getSupportedMembersTabRelations(){ - List relations = WebComponentUtil.getCategoryRelationChoices(AreaCategoryType.ADMINISTRATION, getDetailsPage()); - List governance = WebComponentUtil.getCategoryRelationChoices(AreaCategoryType.GOVERNANCE, getDetailsPage()); - governance.forEach(r -> relations.remove(r)); - return new AvailableRelationDto(relations); - } - - protected AvailableRelationDto getSupportedGovernanceTabRelations(){ - return new AvailableRelationDto(WebComponentUtil.getCategoryRelationChoices(AreaCategoryType.GOVERNANCE, getDetailsPage())); - } - - protected QName getDefaultGovernanceRelation(){ - return WebComponentUtil.getCategoryDefaultRelation(AreaCategoryType.GOVERNANCE); - } - - protected Map getGovernanceTabAuthorizations(){ - return GuiAuthorizationConstants.GOVERNANCE_MEMBERS_AUTHORIZATIONS; - } - - private boolean isAllowedToReadRoleMembership(String abstractRoleOid, PageBase parentPage){ - return isAllowedToReadRoleMembershipItemForType(abstractRoleOid, UserType.class, parentPage) - || isAllowedToReadRoleMembershipItemForType(abstractRoleOid, RoleType.class, parentPage) - || isAllowedToReadRoleMembershipItemForType(abstractRoleOid, OrgType.class, parentPage) - || isAllowedToReadRoleMembershipItemForType(abstractRoleOid, ServiceType.class, parentPage); - } - - private boolean isAllowedToReadRoleMembershipItemForType(String abstractRoleOid, Class type, PageBase parentPage){ - ObjectQuery query = parentPage.getPrismContext().queryFor(type) - .item(FocusType.F_ROLE_MEMBERSHIP_REF).ref(abstractRoleOid).build(); - Task task = parentPage.createSimpleTask(OPERATION_CAN_SEARCH_ROLE_MEMBERSHIP_ITEM); - OperationResult result = task.getResult(); - boolean isAllowed = false; - try { - isAllowed = parentPage.getModelInteractionService() - .canSearch(type, null, null, false, query, task, result); - } catch (Exception ex){ - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't check if user is allowed to search for roleMembershipRef item", ex); - } - return isAllowed; - } - - private String getInducementsCount(){ - PrismObject focus = getObjectModel().getObject().getObject(); - List inducements = focus.asObjectable().getInducement(); - if (inducements == null){ - return ""; - } - return Integer.toString(inducements.size()); - } - - - //TODO what? why? when? - @Override - protected boolean areSavePreviewButtonsEnabled(){ - PrismObjectWrapper focusWrapper = getObjectModel().getObject(); - PrismContainerWrapper assignmentsWrapper; - try { - assignmentsWrapper = focusWrapper.findContainer(AbstractRoleType.F_INDUCEMENT); - } catch (SchemaException e) { - return false; - } - return super.areSavePreviewButtonsEnabled() || isAssignmentsModelChanged(assignmentsWrapper); - } -} +/* + * Copyright (c) 2015-2016 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.component.objectdetails; + +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.wicket.ajax.AjaxChannel; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.attributes.AjaxRequestAttributes; +import org.apache.wicket.behavior.AttributeAppender; +import org.apache.wicket.extensions.markup.html.tabs.ITab; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.model.Model; + +import com.evolveum.midpoint.gui.api.ComponentConstants; +import com.evolveum.midpoint.gui.api.component.tabs.CountablePanelTab; +import com.evolveum.midpoint.gui.api.component.tabs.PanelTab; +import com.evolveum.midpoint.gui.api.model.LoadableModel; +import com.evolveum.midpoint.gui.api.page.PageBase; +import com.evolveum.midpoint.gui.api.prism.ItemStatus; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ShadowWrapper; +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.LoggingUtils; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.component.AjaxButton; +import com.evolveum.midpoint.web.component.assignment.AssignmentEditorDto; +import com.evolveum.midpoint.web.component.assignment.AssignmentsUtil; +import com.evolveum.midpoint.web.component.assignment.SwitchAssignmentTypePanel; +import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; +import com.evolveum.midpoint.web.model.PrismContainerWrapperModel; +import com.evolveum.midpoint.web.page.admin.PageAdminFocus; +import com.evolveum.midpoint.web.page.admin.PageAdminObjectDetails; +import com.evolveum.midpoint.web.page.admin.roles.AbstractRoleMemberPanel; +import com.evolveum.midpoint.web.page.admin.roles.AvailableRelationDto; +import com.evolveum.midpoint.web.page.admin.users.dto.UserDtoStatus; +import com.evolveum.midpoint.web.page.self.PageAssignmentShoppingCart; +import com.evolveum.midpoint.web.security.GuiAuthorizationConstants; +import com.evolveum.midpoint.web.session.RoleCatalogStorage; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AreaCategoryType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ServiceType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; + +/** + * @author semancik + * + */ +public abstract class AbstractRoleMainPanel extends FocusMainPanel { + private static final long serialVersionUID = 1L; + + private static final Trace LOGGER = TraceManager.getTrace(AbstractRoleMainPanel.class); + + private static final String DOT_CLASS = AbstractRoleMainPanel.class.getName(); + private static final String OPERATION_CAN_SEARCH_ROLE_MEMBERSHIP_ITEM = DOT_CLASS + "canSearchRoleMembershipItem"; + private static final String OPERATION_LOAD_ASSIGNMENTS_LIMIT = DOT_CLASS + "loadAssignmentsLimit"; + private static final String ID_SHOPPING_CART_BUTTONS_PANEL = "shoppingCartButtonsPanel"; + private static final String ID_ADD_TO_CART_BUTTON = "addToCartButton"; + + public AbstractRoleMainPanel(String id, LoadableModel> objectModel, + LoadableModel> projectionModel, + PageAdminFocus parentPage) { + super(id, objectModel, projectionModel, parentPage); + } + + @Override + protected void initLayoutButtons(PageAdminObjectDetails parentPage) { + super.initLayoutButtons(parentPage); + initShoppingCartPanel(parentPage); + } + + private void initShoppingCartPanel(PageAdminObjectDetails parentPage){ + RoleCatalogStorage storage = parentPage.getSessionStorage().getRoleCatalog(); + + WebMarkupContainer shoppingCartButtonsPanel = new WebMarkupContainer(ID_SHOPPING_CART_BUTTONS_PANEL); + shoppingCartButtonsPanel.setOutputMarkupId(true); + shoppingCartButtonsPanel.add(new VisibleEnableBehaviour(){ + private static final long serialVersionUID = 1L; + + @Override + public boolean isVisible(){ + //show panel only in case if user came to object details from + // Role Catalog page + return PageAssignmentShoppingCart.class.equals(WebComponentUtil.getPreviousPageClass(parentPage)); + } + }); + getMainForm().add(shoppingCartButtonsPanel); + + AjaxButton addToCartButton = new AjaxButton(ID_ADD_TO_CART_BUTTON, parentPage + .createStringResource("PageAssignmentDetails.addToCartButton")) { + private static final long serialVersionUID = 1L; + + @Override + protected void updateAjaxAttributes(AjaxRequestAttributes attributes) { + attributes.setChannel(new AjaxChannel("blocking", AjaxChannel.Type.ACTIVE)); + } + + @Override + public void onClick(AjaxRequestTarget target) { + AssignmentEditorDto dto = AssignmentEditorDto.createDtoFromObject(getObject().asObjectable(), UserDtoStatus.ADD, parentPage); + storage.getAssignmentShoppingCart().add(dto); + parentPage.redirectBack(); + } + }; + addToCartButton.add(AttributeAppender.append("class", new LoadableModel() { + @Override + protected String load() { + return addToCartButton.isEnabled() ? "btn btn-success" : "btn btn-success disabled"; + } + })); + addToCartButton.setOutputMarkupId(true); + addToCartButton.add(new VisibleEnableBehaviour(){ + private static final long serialVersionUID = 1L; + + @Override + public boolean isEnabled(){ + int assignmentsLimit = AssignmentsUtil.loadAssignmentsLimit(new OperationResult(OPERATION_LOAD_ASSIGNMENTS_LIMIT), + parentPage); + AssignmentEditorDto dto = AssignmentEditorDto.createDtoFromObject(AbstractRoleMainPanel.this.getObject().asObjectable(), + UserDtoStatus.ADD, parentPage); + return !AssignmentsUtil.isShoppingCartAssignmentsLimitReached(assignmentsLimit, parentPage) + && (storage.isMultiUserRequest() || dto.isAssignable()); } + }); + addToCartButton.add(AttributeAppender.append("title", + AssignmentsUtil.getShoppingCartAssignmentsLimitReachedTitleModel(parentPage))); + shoppingCartButtonsPanel.add(addToCartButton); + } + + @Override + protected List createTabs(final PageAdminObjectDetails parentPage) { + List tabs = super.createTabs(parentPage); + + tabs.add( + new PanelTab(parentPage.createStringResource("pageAdminFocus.applicablePolicies"), + getTabVisibility( ComponentConstants.UI_FOCUS_TAB_APPLICABLE_POLICIES_URL, false, parentPage)) { + + private static final long serialVersionUID = 1L; + + @Override + public WebMarkupContainer createPanel(String panelId) { + return new FocusApplicablePoliciesTabPanel<>(panelId, getMainForm(), getObjectModel()); + } + }); + + tabs.add(new CountablePanelTab(parentPage.createStringResource("FocusType.inducement"), + getTabVisibility( ComponentConstants.UI_FOCUS_TAB_INDUCEMENTS_URL, false, parentPage)) { + + private static final long serialVersionUID = 1L; + + @Override + public WebMarkupContainer createPanel(String panelId) { + SwitchAssignmentTypePanel panel = new SwitchAssignmentTypePanel(panelId, + PrismContainerWrapperModel.fromContainerWrapper(getObjectModel(), AbstractRoleType.F_INDUCEMENT)){ + private static final long serialVersionUID = 1L; + + @Override + protected boolean isInducement(){ + return true; + } + }; + return panel; + } + + @Override + public String getCount(){ + return getInducementsCount(); + } + + }); + + tabs.add(new PanelTab(parentPage.createStringResource("pageRole.members"), + getTabVisibility( ComponentConstants.UI_FOCUS_TAB_MEMBERS_URL, false, parentPage)) { + + private static final long serialVersionUID = 1L; + + @Override + public WebMarkupContainer createPanel(String panelId) { + return createMemberPanel(panelId); + } + + @Override + public boolean isVisible() { + return super.isVisible() && + getObjectWrapper().getStatus() != ItemStatus.ADDED && + isAllowedToReadRoleMembership(getObjectWrapper().getOid(), parentPage); + } + }); + + tabs.add(new PanelTab(parentPage.createStringResource("pageRole.governance"), + getTabVisibility( ComponentConstants.UI_FOCUS_TAB_GOVERNANCE_URL, false, parentPage)) { + + private static final long serialVersionUID = 1L; + + @Override + public WebMarkupContainer createPanel(String panelId) { + return createGovernancePanel(panelId); + } + + @Override + public boolean isVisible() { + return super.isVisible() && getObjectWrapper().getStatus() != ItemStatus.ADDED; + } + }); + + return tabs; + } + + + public AbstractRoleMemberPanel createMemberPanel(String panelId) { + + return new AbstractRoleMemberPanel(panelId, new Model<>(getObject().asObjectable())) { + + private static final long serialVersionUID = 1L; + + @Override + protected AvailableRelationDto getSupportedRelations() { + return getSupportedMembersTabRelations(); + } + + }; + } + + + public AbstractRoleMemberPanel createGovernancePanel(String panelId) { + + return new AbstractRoleMemberPanel(panelId, new Model<>(getObject().asObjectable())) { + + private static final long serialVersionUID = 1L; + + @Override + protected AvailableRelationDto getSupportedRelations() { + AvailableRelationDto avariableRelations = getSupportedGovernanceTabRelations(); + avariableRelations.setDefaultRelation(getDefaultGovernanceRelation()); + return avariableRelations; + } + + @Override + protected Map getAuthorizations(QName complexType) { + return getGovernanceTabAuthorizations(); + } + + }; + } + + protected AvailableRelationDto getSupportedMembersTabRelations(){ + List relations = WebComponentUtil.getCategoryRelationChoices(AreaCategoryType.ADMINISTRATION, getDetailsPage()); + List governance = WebComponentUtil.getCategoryRelationChoices(AreaCategoryType.GOVERNANCE, getDetailsPage()); + governance.forEach(r -> relations.remove(r)); + return new AvailableRelationDto(relations); + } + + protected AvailableRelationDto getSupportedGovernanceTabRelations(){ + return new AvailableRelationDto(WebComponentUtil.getCategoryRelationChoices(AreaCategoryType.GOVERNANCE, getDetailsPage())); + } + + protected QName getDefaultGovernanceRelation(){ + return WebComponentUtil.getCategoryDefaultRelation(AreaCategoryType.GOVERNANCE); + } + + protected Map getGovernanceTabAuthorizations(){ + return GuiAuthorizationConstants.GOVERNANCE_MEMBERS_AUTHORIZATIONS; + } + + private boolean isAllowedToReadRoleMembership(String abstractRoleOid, PageBase parentPage){ + return isAllowedToReadRoleMembershipItemForType(abstractRoleOid, UserType.class, parentPage) + || isAllowedToReadRoleMembershipItemForType(abstractRoleOid, RoleType.class, parentPage) + || isAllowedToReadRoleMembershipItemForType(abstractRoleOid, OrgType.class, parentPage) + || isAllowedToReadRoleMembershipItemForType(abstractRoleOid, ServiceType.class, parentPage); + } + + private boolean isAllowedToReadRoleMembershipItemForType(String abstractRoleOid, Class type, PageBase parentPage){ + ObjectQuery query = parentPage.getPrismContext().queryFor(type) + .item(FocusType.F_ROLE_MEMBERSHIP_REF).ref(abstractRoleOid).build(); + Task task = parentPage.createSimpleTask(OPERATION_CAN_SEARCH_ROLE_MEMBERSHIP_ITEM); + OperationResult result = task.getResult(); + boolean isAllowed = false; + try { + isAllowed = parentPage.getModelInteractionService() + .canSearch(type, null, null, false, query, task, result); + } catch (Exception ex){ + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't check if user is allowed to search for roleMembershipRef item", ex); + } + return isAllowed; + } + + private String getInducementsCount(){ + PrismObject focus = getObjectModel().getObject().getObject(); + List inducements = focus.asObjectable().getInducement(); + if (inducements == null){ + return ""; + } + return Integer.toString(inducements.size()); + } + + + //TODO what? why? when? + @Override + protected boolean areSavePreviewButtonsEnabled(){ + PrismObjectWrapper focusWrapper = getObjectModel().getObject(); + PrismContainerWrapper assignmentsWrapper; + try { + assignmentsWrapper = focusWrapper.findContainer(AbstractRoleType.F_INDUCEMENT); + } catch (SchemaException e) { + return false; + } + return super.areSavePreviewButtonsEnabled() || isAssignmentsModelChanged(assignmentsWrapper); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AssignmentHolderTypeAssignmentsTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AssignmentHolderTypeAssignmentsTabPanel.java index d01338b0483..eb13825c2c1 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AssignmentHolderTypeAssignmentsTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AssignmentHolderTypeAssignmentsTabPanel.java @@ -1,75 +1,75 @@ -/* - * Copyright (c) 2010-2017 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.component.objectdetails; - -import com.evolveum.midpoint.web.page.admin.server.RefreshableTabPanel; - -import org.apache.wicket.Component; -import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.model.Model; - -import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.web.component.assignment.SwitchAssignmentTypePanel; -import com.evolveum.midpoint.web.component.form.Form; -import com.evolveum.midpoint.web.model.PrismContainerWrapperModel; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentHolderType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; - -import java.util.Collection; -import java.util.Collections; - -/** - * @author semancik - */ -public class AssignmentHolderTypeAssignmentsTabPanel extends AbstractObjectTabPanel implements RefreshableTabPanel { - private static final long serialVersionUID = 1L; - - private static final String ID_ASSIGNMENTS = "assignmentsContainer"; - private static final String ID_ASSIGNMENTS_PANEL = "assignmentsPanel"; - - public AssignmentHolderTypeAssignmentsTabPanel(String id, Form> mainForm, LoadableModel> focusWrapperModel) { - super(id, mainForm, focusWrapperModel); - - } - - @Override - protected void onInitialize() { - super.onInitialize(); - initLayout(); - } - - private void initLayout() { - WebMarkupContainer assignments = new WebMarkupContainer(ID_ASSIGNMENTS); - assignments.setOutputMarkupId(true); - add(assignments); - PrismContainerWrapperModel model = PrismContainerWrapperModel.fromContainerWrapper(getObjectWrapperModel(), AssignmentHolderType.F_ASSIGNMENT); - SwitchAssignmentTypePanel panel = createPanel(ID_ASSIGNMENTS_PANEL, model); - - assignments.add(panel); - } - - protected SwitchAssignmentTypePanel createPanel(String panelId, PrismContainerWrapperModel model) { - return new SwitchAssignmentTypePanel(panelId, model != null ? model : Model.of()){ - private static final long serialVersionUID = 1L; - - @Override - protected boolean isReadonly(){ - return AssignmentHolderTypeAssignmentsTabPanel.this.isReadonly(); - } - }; - } - - protected boolean isReadonly(){ - return false; - } - - @Override - public Collection getComponentsToUpdate() { - return Collections.singleton(this); - } -} +/* + * Copyright (c) 2010-2017 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.component.objectdetails; + +import com.evolveum.midpoint.web.page.admin.server.RefreshableTabPanel; + +import org.apache.wicket.Component; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.model.Model; + +import com.evolveum.midpoint.gui.api.model.LoadableModel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.web.component.assignment.SwitchAssignmentTypePanel; +import com.evolveum.midpoint.web.component.form.Form; +import com.evolveum.midpoint.web.model.PrismContainerWrapperModel; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentHolderType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; + +import java.util.Collection; +import java.util.Collections; + +/** + * @author semancik + */ +public class AssignmentHolderTypeAssignmentsTabPanel extends AbstractObjectTabPanel implements RefreshableTabPanel { + private static final long serialVersionUID = 1L; + + private static final String ID_ASSIGNMENTS = "assignmentsContainer"; + private static final String ID_ASSIGNMENTS_PANEL = "assignmentsPanel"; + + public AssignmentHolderTypeAssignmentsTabPanel(String id, Form> mainForm, LoadableModel> focusWrapperModel) { + super(id, mainForm, focusWrapperModel); + + } + + @Override + protected void onInitialize() { + super.onInitialize(); + initLayout(); + } + + private void initLayout() { + WebMarkupContainer assignments = new WebMarkupContainer(ID_ASSIGNMENTS); + assignments.setOutputMarkupId(true); + add(assignments); + PrismContainerWrapperModel model = PrismContainerWrapperModel.fromContainerWrapper(getObjectWrapperModel(), AssignmentHolderType.F_ASSIGNMENT); + SwitchAssignmentTypePanel panel = createPanel(ID_ASSIGNMENTS_PANEL, model); + + assignments.add(panel); + } + + protected SwitchAssignmentTypePanel createPanel(String panelId, PrismContainerWrapperModel model) { + return new SwitchAssignmentTypePanel(panelId, model != null ? model : Model.of()){ + private static final long serialVersionUID = 1L; + + @Override + protected boolean isReadonly(){ + return AssignmentHolderTypeAssignmentsTabPanel.this.isReadonly(); + } + }; + } + + protected boolean isReadonly(){ + return false; + } + + @Override + public Collection getComponentsToUpdate() { + return Collections.singleton(this); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AssignmentHolderTypeDetailsTabPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AssignmentHolderTypeDetailsTabPanel.html index bdc4e99a22a..913a6d4c73b 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AssignmentHolderTypeDetailsTabPanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AssignmentHolderTypeDetailsTabPanel.html @@ -10,11 +10,21 @@ xmlns:wicket="http://wicket.apache.org"> -
-
-
-
-
+
+
+
+
+ +
+
+
+ + +
+
+
+ +
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AssignmentHolderTypeDetailsTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AssignmentHolderTypeDetailsTabPanel.java index 047079facbb..696ed99cab0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AssignmentHolderTypeDetailsTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AssignmentHolderTypeDetailsTabPanel.java @@ -1,78 +1,81 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.component.objectdetails; - -import java.util.Collection; -import java.util.Collections; - -import org.apache.wicket.Component; -import org.apache.wicket.markup.html.panel.Panel; - -import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.impl.prism.ItemPanelSettingsBuilder; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.util.exception.SchemaException; -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.ItemVisibility; -import com.evolveum.midpoint.web.model.PrismContainerWrapperModel; -import com.evolveum.midpoint.web.page.admin.server.RefreshableTabPanel; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; - -/** - * @author semancik - */ -public class AssignmentHolderTypeDetailsTabPanel extends AbstractObjectTabPanel implements RefreshableTabPanel { - private static final long serialVersionUID = 1L; - - private static final String ID_MAIN_PANEL = "main"; - private static final String ID_ACTIVATION_PANEL = "activation"; - private static final String ID_PASSWORD_PANEL = "password"; - - private static final Trace LOGGER = TraceManager.getTrace(AssignmentHolderTypeDetailsTabPanel.class); - - public AssignmentHolderTypeDetailsTabPanel(String id, Form> mainForm, - LoadableModel> focusWrapperModel) { - super(id, mainForm, focusWrapperModel); - - } - - @Override - protected void onInitialize() { - super.onInitialize(); - initLayout(); - } - - private void initLayout() { - - try { - - ItemPanelSettingsBuilder builder = new ItemPanelSettingsBuilder().visibilityHandler(w -> ItemVisibility.AUTO).showOnTopLevel(true); - builder.headerVisibility(false); - - Panel main = getPageBase().initItemPanel(ID_MAIN_PANEL, getObjectWrapper().getTypeName(), - PrismContainerWrapperModel.fromContainerWrapper(getObjectWrapperModel(), ItemPath.EMPTY_PATH), builder.build()); - add(main); - Panel activation = getPageBase().initItemPanel(ID_ACTIVATION_PANEL, ActivationType.COMPLEX_TYPE, - PrismContainerWrapperModel.fromContainerWrapper(getObjectWrapperModel(), FocusType.F_ACTIVATION), builder.build()); - add(activation); - Panel password = getPageBase().initItemPanel(ID_PASSWORD_PANEL, PasswordType.COMPLEX_TYPE, - PrismContainerWrapperModel.fromContainerWrapper(getObjectWrapperModel(), ItemPath.create(UserType.F_CREDENTIALS, CredentialsType.F_PASSWORD)), builder.build()); - add(password); - } catch (SchemaException e) { - LOGGER.error("Could not create focus details panel. Reason: {}", e.getMessage(), e); - } - } - - @Override - public Collection getComponentsToUpdate() { - getObjectWrapperModel().reset(); - return Collections.singleton(this); - } -} +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.component.objectdetails; + +import java.util.Collection; +import java.util.Collections; + +import com.evolveum.midpoint.gui.impl.prism.panel.ItemHeaderPanel; + +import com.evolveum.midpoint.gui.impl.prism.panel.ItemPanelSettingsBuilder; + +import org.apache.wicket.Component; +import org.apache.wicket.markup.html.panel.Panel; + +import com.evolveum.midpoint.gui.api.model.LoadableModel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.util.exception.SchemaException; +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.ItemVisibility; +import com.evolveum.midpoint.web.model.PrismContainerWrapperModel; +import com.evolveum.midpoint.web.page.admin.server.RefreshableTabPanel; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; + +/** + * @author semancik + */ +public class AssignmentHolderTypeDetailsTabPanel extends AbstractObjectTabPanel implements RefreshableTabPanel { + private static final long serialVersionUID = 1L; + + private static final String ID_MAIN_PANEL = "main"; + private static final String ID_ACTIVATION_PANEL = "activation"; + private static final String ID_PASSWORD_PANEL = "password"; + + private static final Trace LOGGER = TraceManager.getTrace(AssignmentHolderTypeDetailsTabPanel.class); + + public AssignmentHolderTypeDetailsTabPanel(String id, Form> mainForm, + LoadableModel> focusWrapperModel) { + super(id, mainForm, focusWrapperModel); + + } + + @Override + protected void onInitialize() { + super.onInitialize(); + initLayout(); + } + + private void initLayout() { + + try { + + ItemPanelSettingsBuilder builder = new ItemPanelSettingsBuilder().visibilityHandler(w -> ItemVisibility.AUTO); + builder.headerVisibility(false); + + Panel main = getPageBase().initItemPanel(ID_MAIN_PANEL, getObjectWrapper().getTypeName(), + PrismContainerWrapperModel.fromContainerWrapper(getObjectWrapperModel(), ItemPath.EMPTY_PATH), builder.build()); + add(main); + Panel activation = getPageBase().initItemPanel(ID_ACTIVATION_PANEL, ActivationType.COMPLEX_TYPE, + PrismContainerWrapperModel.fromContainerWrapper(getObjectWrapperModel(), FocusType.F_ACTIVATION), builder.build()); + add(activation); + Panel password = getPageBase().initItemPanel(ID_PASSWORD_PANEL, PasswordType.COMPLEX_TYPE, + PrismContainerWrapperModel.fromContainerWrapper(getObjectWrapperModel(), ItemPath.create(UserType.F_CREDENTIALS, CredentialsType.F_PASSWORD)), builder.build()); + add(password); + } catch (SchemaException e) { + LOGGER.error("Could not create focus details panel. Reason: {}", e.getMessage(), e); + } + } + + @Override + public Collection getComponentsToUpdate() { + getObjectWrapperModel().reset(); + return Collections.singleton(this); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AssignmentHolderTypeMainPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AssignmentHolderTypeMainPanel.java index a7275e022ec..607f944a117 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AssignmentHolderTypeMainPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/AssignmentHolderTypeMainPanel.java @@ -1,118 +1,118 @@ -/* - * Copyright (c) 2015-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.component.objectdetails; - -import com.evolveum.midpoint.gui.api.ComponentConstants; -import com.evolveum.midpoint.gui.api.component.tabs.CountablePanelTab; -import com.evolveum.midpoint.gui.api.component.tabs.PanelTab; -import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.api.util.ObjectTabVisibleBehavior; -import com.evolveum.midpoint.gui.api.util.HistoryPageTabVisibleBehavior; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.web.component.assignment.AssignmentsUtil; -import com.evolveum.midpoint.web.page.admin.PageAdminObjectDetails; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentHolderType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; -import org.apache.wicket.extensions.markup.html.tabs.ITab; -import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.model.IModel; - -import java.util.ArrayList; -import java.util.List; - - -/** - * Created by honchar - */ -public class AssignmentHolderTypeMainPanel extends AbstractObjectMainPanel{ - private static final long serialVersionUID = 1L; - - public AssignmentHolderTypeMainPanel(String id, LoadableModel> objectModel, - PageAdminObjectDetails parentPage) { - super(id, objectModel, parentPage); - } - - @Override - protected List createTabs(final PageAdminObjectDetails parentPage) { - List tabs = new ArrayList<>(); - - tabs.add( - new PanelTab(parentPage.createStringResource("pageAdminFocus.basic"), - getTabVisibility(ComponentConstants.UI_FOCUS_TAB_BASIC_URL, true, parentPage)){ - - private static final long serialVersionUID = 1L; - - @Override - public WebMarkupContainer createPanel(String panelId) { - return new AssignmentHolderTypeDetailsTabPanel<>(panelId, getMainForm(), getObjectModel()); - } - }); - - tabs.add( - new CountablePanelTab(parentPage.createStringResource("pageAdminFocus.assignments"), - getTabVisibility(ComponentConstants.UI_FOCUS_TAB_ASSIGNMENTS_URL, true, parentPage)) { - - private static final long serialVersionUID = 1L; - - @Override - public WebMarkupContainer createPanel(String panelId) { - return new AssignmentHolderTypeAssignmentsTabPanel(panelId, getMainForm(), getObjectModel()){ - private static final long serialVersionUID = 1L; - - @Override - protected boolean isReadonly(){ - return AssignmentHolderTypeMainPanel.this.isReadonly(); - } - }; - } - - @Override - public String getCount() { - return Integer.toString(countAssignments()); - } - }); - - return tabs; - } - - protected IModel> unwrapModel() { - return (IModel>) () -> getObjectWrapper().getObject(); - } - - protected ObjectTabVisibleBehavior getTabVisibility(String authUrl, boolean isVisibleOnHistoryPage, PageAdminObjectDetails parentPage){ - if (isFocusHistoryPage()){ - return new HistoryPageTabVisibleBehavior<>(unwrapModel(), authUrl, isVisibleOnHistoryPage, parentPage); - } else { - return new ObjectTabVisibleBehavior<>(unwrapModel(), authUrl, parentPage); - } - } - - protected boolean isFocusHistoryPage(){ - return false; - } - - protected int countAssignments() { - int rv = 0; - PrismObject focus = getObjectModel().getObject().getObject(); - List assignments = focus.asObjectable().getAssignment(); - for (AssignmentType assignment : assignments) { - if (!AssignmentsUtil.isConsentAssignment(assignment) - && AssignmentsUtil.isAssignmentRelevant(assignment) && !AssignmentsUtil.isArchetypeAssignment(assignment)) { - rv++; - } - } - return rv; - } - - //this value will be used independently of object wrapper isReadonly value, - protected boolean isReadonly(){ - return false; - } - - -} +/* + * Copyright (c) 2015-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.component.objectdetails; + +import com.evolveum.midpoint.gui.api.ComponentConstants; +import com.evolveum.midpoint.gui.api.component.tabs.CountablePanelTab; +import com.evolveum.midpoint.gui.api.component.tabs.PanelTab; +import com.evolveum.midpoint.gui.api.model.LoadableModel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.util.ObjectTabVisibleBehavior; +import com.evolveum.midpoint.gui.api.util.HistoryPageTabVisibleBehavior; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.web.component.assignment.AssignmentsUtil; +import com.evolveum.midpoint.web.page.admin.PageAdminObjectDetails; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentHolderType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import org.apache.wicket.extensions.markup.html.tabs.ITab; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.model.IModel; + +import java.util.ArrayList; +import java.util.List; + + +/** + * Created by honchar + */ +public class AssignmentHolderTypeMainPanel extends AbstractObjectMainPanel{ + private static final long serialVersionUID = 1L; + + public AssignmentHolderTypeMainPanel(String id, LoadableModel> objectModel, + PageAdminObjectDetails parentPage) { + super(id, objectModel, parentPage); + } + + @Override + protected List createTabs(final PageAdminObjectDetails parentPage) { + List tabs = new ArrayList<>(); + + tabs.add( + new PanelTab(parentPage.createStringResource("pageAdminFocus.basic"), + getTabVisibility(ComponentConstants.UI_FOCUS_TAB_BASIC_URL, true, parentPage)){ + + private static final long serialVersionUID = 1L; + + @Override + public WebMarkupContainer createPanel(String panelId) { + return new AssignmentHolderTypeDetailsTabPanel<>(panelId, getMainForm(), getObjectModel()); + } + }); + + tabs.add( + new CountablePanelTab(parentPage.createStringResource("pageAdminFocus.assignments"), + getTabVisibility(ComponentConstants.UI_FOCUS_TAB_ASSIGNMENTS_URL, true, parentPage)) { + + private static final long serialVersionUID = 1L; + + @Override + public WebMarkupContainer createPanel(String panelId) { + return new AssignmentHolderTypeAssignmentsTabPanel(panelId, getMainForm(), getObjectModel()){ + private static final long serialVersionUID = 1L; + + @Override + protected boolean isReadonly(){ + return AssignmentHolderTypeMainPanel.this.isReadonly(); + } + }; + } + + @Override + public String getCount() { + return Integer.toString(countAssignments()); + } + }); + + return tabs; + } + + protected IModel> unwrapModel() { + return (IModel>) () -> getObjectWrapper().getObject(); + } + + protected ObjectTabVisibleBehavior getTabVisibility(String authUrl, boolean isVisibleOnHistoryPage, PageAdminObjectDetails parentPage){ + if (isFocusHistoryPage()){ + return new HistoryPageTabVisibleBehavior<>(unwrapModel(), authUrl, isVisibleOnHistoryPage, parentPage); + } else { + return new ObjectTabVisibleBehavior<>(unwrapModel(), authUrl, parentPage); + } + } + + protected boolean isFocusHistoryPage(){ + return false; + } + + protected int countAssignments() { + int rv = 0; + PrismObject focus = getObjectModel().getObject().getObject(); + List assignments = focus.asObjectable().getAssignment(); + for (AssignmentType assignment : assignments) { + if (!AssignmentsUtil.isConsentAssignment(assignment) + && AssignmentsUtil.isAssignmentRelevant(assignment) && !AssignmentsUtil.isArchetypeAssignment(assignment)) { + rv++; + } + } + return rv; + } + + //this value will be used independently of object wrapper isReadonly value, + protected boolean isReadonly(){ + return false; + } + + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusApplicablePoliciesTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusApplicablePoliciesTabPanel.java index b808ae18848..e7f4c258f95 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusApplicablePoliciesTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusApplicablePoliciesTabPanel.java @@ -10,7 +10,7 @@ import org.apache.wicket.markup.html.WebMarkupContainer; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.web.component.assignment.ApplicablePolicyConfigPanel; import com.evolveum.midpoint.web.component.form.Form; import com.evolveum.midpoint.web.model.PrismContainerWrapperModel; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusConsentTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusConsentTabPanel.java index 1993095f388..82e1ec874a8 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusConsentTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusConsentTabPanel.java @@ -7,7 +7,7 @@ package com.evolveum.midpoint.web.component.objectdetails; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.web.component.assignment.GdprAssignmentPanel; import com.evolveum.midpoint.web.component.form.Form; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusMainPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusMainPanel.java index bc3d844da5a..5cfe8d2f63c 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusMainPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusMainPanel.java @@ -1,296 +1,296 @@ -/* - * Copyright (c) 2015-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.component.objectdetails; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.List; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.Validate; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.extensions.markup.html.tabs.ITab; -import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.model.IModel; - -import com.evolveum.midpoint.gui.api.ComponentConstants; -import com.evolveum.midpoint.gui.api.component.tabs.CountablePanelTab; -import com.evolveum.midpoint.gui.api.component.tabs.PanelTab; -import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.api.prism.ShadowWrapper; -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.model.api.ModelAuthorizationAction; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SystemException; -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.ValueStatus; -import com.evolveum.midpoint.web.page.admin.PageAdminObjectDetails; -import com.evolveum.midpoint.wf.util.QueryUtils; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; - -/** - * @author semancik - * - */ -public class FocusMainPanel extends AssignmentHolderTypeMainPanel { - - private static final long serialVersionUID = 1L; - - private static final Trace LOGGER = TraceManager.getTrace(FocusMainPanel.class); - - private LoadableModel> projectionModel; - - public FocusMainPanel(String id, LoadableModel> objectModel, - LoadableModel> projectionModel, - PageAdminObjectDetails parentPage) { - super(id, objectModel, parentPage); - Validate.notNull(projectionModel, "Null projection model"); - this.projectionModel = projectionModel; - } - - @Override - protected void onInitialize() { - super.onInitialize(); - - getMainForm().setMultiPart(true); - } - - @Override - protected List createTabs(final PageAdminObjectDetails parentPage) { - List tabs = super.createTabs(parentPage); - - List objectFormTypes = parentPage.getObjectFormTypes(); - // default tabs are always added to component structure, visibility is decided later in - // visible behavior based on adminGuiConfiguration - addDefaultTabs(parentPage, tabs); - addSpecificTabs(parentPage, tabs); - if (objectFormTypes == null) { - return tabs; - } - - for (ObjectFormType objectFormType : objectFormTypes) { - final FormSpecificationType formSpecificationType = objectFormType.getFormSpecification(); - if (formSpecificationType == null){ - continue; - } - String title = formSpecificationType.getTitle(); - if (title == null) { - title = "pageAdminFocus.extended"; - } - - if (StringUtils.isEmpty(formSpecificationType.getPanelClass())) { - continue; - } - - tabs.add( - new PanelTab(parentPage.createStringResource(title)) { - private static final long serialVersionUID = 1L; - - @Override - public WebMarkupContainer createPanel(String panelId) { - return createTabPanel(panelId, formSpecificationType); - } - }); - } - - return tabs; - } - - protected WebMarkupContainer createTabPanel(String panelId, FormSpecificationType formSpecificationType) { - String panelClassName = formSpecificationType.getPanelClass(); - - Class panelClass; - try { - panelClass = Class.forName(panelClassName); - } catch (ClassNotFoundException e) { - throw new SystemException("Panel class '"+panelClassName+"' as specified in admin GUI configuration was not found", e); - } - if (AbstractFocusTabPanel.class.isAssignableFrom(panelClass)) { - Constructor constructor; - try { - constructor = panelClass.getConstructor(String.class, Form.class, LoadableModel.class, LoadableModel.class); - } catch (NoSuchMethodException | SecurityException e) { - throw new SystemException("Unable to locate constructor (String,Form,LoadableModel,LoadableModel,LoadableModel,PageBase) in "+panelClass+": "+e.getMessage(), e); - } - AbstractFocusTabPanel tabPanel; - try { - tabPanel = (AbstractFocusTabPanel) constructor.newInstance(panelId, getMainForm(), getObjectModel(), projectionModel); - } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new SystemException("Error instantiating "+panelClass+": "+e.getMessage(), e); - } - return tabPanel; - } else if (AbstractObjectTabPanel.class.isAssignableFrom(panelClass)) { - Constructor constructor; - try { - constructor = panelClass.getConstructor(String.class, Form.class, LoadableModel.class); - } catch (NoSuchMethodException | SecurityException e) { - throw new SystemException("Unable to locate constructor (String,Form,LoadableModel,PageBase) in "+panelClass+": "+e.getMessage(), e); - } - AbstractObjectTabPanel tabPanel; - try { - tabPanel = (AbstractObjectTabPanel) constructor.newInstance(panelId, getMainForm(), getObjectModel()); - } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new SystemException("Error instantiating "+panelClass+": "+e.getMessage(), e); - } - return tabPanel; - - } else { - throw new UnsupportedOperationException("Tab panels that are not subclasses of AbstractObjectTabPanel or AbstractFocusTabPanel are not supported yet (got "+panelClass+")"); - } - } - - protected WebMarkupContainer createFocusProjectionsTabPanel(String panelId) { - return new FocusProjectionsTabPanel<>(panelId, getMainForm(), getObjectModel(), projectionModel); - } - - protected WebMarkupContainer createObjectHistoryTabPanel(String panelId) { - return new ObjectHistoryTabPanel(panelId, getMainForm(), getObjectModel()){ - protected void currentStateButtonClicked(AjaxRequestTarget target, PrismObject object, String date){ - viewObjectHistoricalDataPerformed(target, object, date); - } - }; - } - - protected void viewObjectHistoricalDataPerformed(AjaxRequestTarget target, PrismObject object, String date){ - } - - protected IModel> unwrapModel() { - return (IModel>) () -> getObjectWrapper().getObject(); - } - - protected void addSpecificTabs(final PageAdminObjectDetails parentPage, List tabs) { - } - - private void addDefaultTabs(final PageAdminObjectDetails parentPage, List tabs) { - - tabs.add(1, - new CountablePanelTab(parentPage.createStringResource("pageAdminFocus.projections"), - getTabVisibility(ComponentConstants.UI_FOCUS_TAB_PROJECTIONS_URL, false, parentPage)){ - - private static final long serialVersionUID = 1L; - - @Override - public WebMarkupContainer createPanel(String panelId) { - return createFocusProjectionsTabPanel(panelId); - } - - @Override - public String getCount() { - return Integer.toString(projectionModel.getObject() == null ? 0 : projectionModel.getObject().size()); - } - }); - - if (WebComponentUtil.isAuthorized(ModelAuthorizationAction.AUDIT_READ.getUrl()) && getObjectWrapper().getStatus() != ItemStatus.ADDED){ - tabs.add( - new PanelTab(parentPage.createStringResource("pageAdminFocus.objectHistory"), - getTabVisibility(ComponentConstants.UI_FOCUS_TAB_OBJECT_HISTORY_URL, false, parentPage)){ - - private static final long serialVersionUID = 1L; - - @Override - public WebMarkupContainer createPanel(String panelId) { - return createObjectHistoryTabPanel(panelId); - } - }); - } - - tabs.add( - new CountablePanelTab(parentPage.createStringResource("pageAdminFocus.cases"), - getTabVisibility(ComponentConstants.UI_FOCUS_TAB_TASKS_URL, false, parentPage)){ - - private static final long serialVersionUID = 1L; - - @Override - public WebMarkupContainer createPanel(String panelId) { - return new FocusTasksTabPanel<>(panelId, getMainForm(), getObjectModel(), - countFocusObjectTasks(parentPage) > 0); - } - - @Override - public String getCount() { - return Integer.toString(countFocusObjectTasks(parentPage)); - } - }); - - tabs.add( - new CountablePanelTab(parentPage.createStringResource("pageAdminFocus.triggers"), - getTabVisibility(ComponentConstants.UI_FOCUS_TAB_TASKS_URL, false, parentPage)){ - - private static final long serialVersionUID = 1L; - - @Override - public WebMarkupContainer createPanel(String panelId) { - return new FocusTriggersTabPanel<>(panelId, getMainForm(), getObjectModel()); - } - - @Override - public String getCount() { - return Integer.toString(countFocusObjectTriggers()); - } - }); - - } - - private int countFocusObjectTasks(PageBase parentPage){ - String oid; - if (getObjectWrapper() == null || StringUtils.isEmpty(getObjectWrapper().getOid())) { - oid = "non-existent"; - } else { - oid = getObjectWrapper().getOid(); - } - ObjectQuery casesQuery = QueryUtils.filterForCasesOverUser(parentPage.getPrismContext().queryFor(CaseType.class), oid) - .desc(ItemPath.create(CaseType.F_METADATA, MetadataType.F_CREATE_TIMESTAMP)) - .build(); - return WebModelServiceUtils.countObjects(CaseType.class, casesQuery, parentPage); - } - - private int countFocusObjectTriggers(){ - PrismObjectWrapper objectWrapper = getObjectWrapper(); - if (objectWrapper.getObject() != null){ - F focusObject = objectWrapper.getObject().asObjectable(); - return focusObject.getTrigger() != null ? focusObject.getTrigger().size() : 0; - } - return 0; - } - - @Override - protected boolean areSavePreviewButtonsEnabled() { - PrismObjectWrapper focusWrapper = getObjectModel().getObject(); - PrismContainerWrapper assignmentsWrapper; - try { - assignmentsWrapper = focusWrapper.findContainer(FocusType.F_ASSIGNMENT); - } catch (SchemaException e) { - LOGGER.error("Cannot find assignment wrapper: {}", e.getMessage()); - return false; - } - return isAssignmentsModelChanged(assignmentsWrapper); - } - - protected boolean isAssignmentsModelChanged(PrismContainerWrapper assignmentsWrapper){ - if (assignmentsWrapper != null) { - for (PrismContainerValueWrapper assignmentWrapper : assignmentsWrapper.getValues()) { - if (ValueStatus.DELETED.equals(assignmentWrapper.getStatus()) || - ValueStatus.ADDED.equals(assignmentWrapper.getStatus())) { - return true; - } - } - } - return false; - } - -} +/* + * Copyright (c) 2015-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.component.objectdetails; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.Validate; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.extensions.markup.html.tabs.ITab; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.model.IModel; + +import com.evolveum.midpoint.gui.api.ComponentConstants; +import com.evolveum.midpoint.gui.api.component.tabs.CountablePanelTab; +import com.evolveum.midpoint.gui.api.component.tabs.PanelTab; +import com.evolveum.midpoint.gui.api.model.LoadableModel; +import com.evolveum.midpoint.gui.api.page.PageBase; +import com.evolveum.midpoint.gui.api.prism.ItemStatus; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ShadowWrapper; +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.model.api.ModelAuthorizationAction; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.exception.SystemException; +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.ValueStatus; +import com.evolveum.midpoint.web.page.admin.PageAdminObjectDetails; +import com.evolveum.midpoint.wf.util.QueryUtils; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; + +/** + * @author semancik + * + */ +public class FocusMainPanel extends AssignmentHolderTypeMainPanel { + + private static final long serialVersionUID = 1L; + + private static final Trace LOGGER = TraceManager.getTrace(FocusMainPanel.class); + + private LoadableModel> projectionModel; + + public FocusMainPanel(String id, LoadableModel> objectModel, + LoadableModel> projectionModel, + PageAdminObjectDetails parentPage) { + super(id, objectModel, parentPage); + Validate.notNull(projectionModel, "Null projection model"); + this.projectionModel = projectionModel; + } + + @Override + protected void onInitialize() { + super.onInitialize(); + + getMainForm().setMultiPart(true); + } + + @Override + protected List createTabs(final PageAdminObjectDetails parentPage) { + List tabs = super.createTabs(parentPage); + + List objectFormTypes = parentPage.getObjectFormTypes(); + // default tabs are always added to component structure, visibility is decided later in + // visible behavior based on adminGuiConfiguration + addDefaultTabs(parentPage, tabs); + addSpecificTabs(parentPage, tabs); + if (objectFormTypes == null) { + return tabs; + } + + for (ObjectFormType objectFormType : objectFormTypes) { + final FormSpecificationType formSpecificationType = objectFormType.getFormSpecification(); + if (formSpecificationType == null){ + continue; + } + String title = formSpecificationType.getTitle(); + if (title == null) { + title = "pageAdminFocus.extended"; + } + + if (StringUtils.isEmpty(formSpecificationType.getPanelClass())) { + continue; + } + + tabs.add( + new PanelTab(parentPage.createStringResource(title)) { + private static final long serialVersionUID = 1L; + + @Override + public WebMarkupContainer createPanel(String panelId) { + return createTabPanel(panelId, formSpecificationType); + } + }); + } + + return tabs; + } + + protected WebMarkupContainer createTabPanel(String panelId, FormSpecificationType formSpecificationType) { + String panelClassName = formSpecificationType.getPanelClass(); + + Class panelClass; + try { + panelClass = Class.forName(panelClassName); + } catch (ClassNotFoundException e) { + throw new SystemException("Panel class '"+panelClassName+"' as specified in admin GUI configuration was not found", e); + } + if (AbstractFocusTabPanel.class.isAssignableFrom(panelClass)) { + Constructor constructor; + try { + constructor = panelClass.getConstructor(String.class, Form.class, LoadableModel.class, LoadableModel.class); + } catch (NoSuchMethodException | SecurityException e) { + throw new SystemException("Unable to locate constructor (String,Form,LoadableModel,LoadableModel,LoadableModel,PageBase) in "+panelClass+": "+e.getMessage(), e); + } + AbstractFocusTabPanel tabPanel; + try { + tabPanel = (AbstractFocusTabPanel) constructor.newInstance(panelId, getMainForm(), getObjectModel(), projectionModel); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new SystemException("Error instantiating "+panelClass+": "+e.getMessage(), e); + } + return tabPanel; + } else if (AbstractObjectTabPanel.class.isAssignableFrom(panelClass)) { + Constructor constructor; + try { + constructor = panelClass.getConstructor(String.class, Form.class, LoadableModel.class); + } catch (NoSuchMethodException | SecurityException e) { + throw new SystemException("Unable to locate constructor (String,Form,LoadableModel,PageBase) in "+panelClass+": "+e.getMessage(), e); + } + AbstractObjectTabPanel tabPanel; + try { + tabPanel = (AbstractObjectTabPanel) constructor.newInstance(panelId, getMainForm(), getObjectModel()); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new SystemException("Error instantiating "+panelClass+": "+e.getMessage(), e); + } + return tabPanel; + + } else { + throw new UnsupportedOperationException("Tab panels that are not subclasses of AbstractObjectTabPanel or AbstractFocusTabPanel are not supported yet (got "+panelClass+")"); + } + } + + protected WebMarkupContainer createFocusProjectionsTabPanel(String panelId) { + return new FocusProjectionsTabPanel<>(panelId, getMainForm(), getObjectModel(), projectionModel); + } + + protected WebMarkupContainer createObjectHistoryTabPanel(String panelId) { + return new ObjectHistoryTabPanel(panelId, getMainForm(), getObjectModel()){ + protected void currentStateButtonClicked(AjaxRequestTarget target, PrismObject object, String date){ + viewObjectHistoricalDataPerformed(target, object, date); + } + }; + } + + protected void viewObjectHistoricalDataPerformed(AjaxRequestTarget target, PrismObject object, String date){ + } + + protected IModel> unwrapModel() { + return (IModel>) () -> getObjectWrapper().getObject(); + } + + protected void addSpecificTabs(final PageAdminObjectDetails parentPage, List tabs) { + } + + private void addDefaultTabs(final PageAdminObjectDetails parentPage, List tabs) { + + tabs.add(1, + new CountablePanelTab(parentPage.createStringResource("pageAdminFocus.projections"), + getTabVisibility(ComponentConstants.UI_FOCUS_TAB_PROJECTIONS_URL, false, parentPage)){ + + private static final long serialVersionUID = 1L; + + @Override + public WebMarkupContainer createPanel(String panelId) { + return createFocusProjectionsTabPanel(panelId); + } + + @Override + public String getCount() { + return Integer.toString(projectionModel.getObject() == null ? 0 : projectionModel.getObject().size()); + } + }); + + if (WebComponentUtil.isAuthorized(ModelAuthorizationAction.AUDIT_READ.getUrl()) && getObjectWrapper().getStatus() != ItemStatus.ADDED){ + tabs.add( + new PanelTab(parentPage.createStringResource("pageAdminFocus.objectHistory"), + getTabVisibility(ComponentConstants.UI_FOCUS_TAB_OBJECT_HISTORY_URL, false, parentPage)){ + + private static final long serialVersionUID = 1L; + + @Override + public WebMarkupContainer createPanel(String panelId) { + return createObjectHistoryTabPanel(panelId); + } + }); + } + + tabs.add( + new CountablePanelTab(parentPage.createStringResource("pageAdminFocus.cases"), + getTabVisibility(ComponentConstants.UI_FOCUS_TAB_TASKS_URL, false, parentPage)){ + + private static final long serialVersionUID = 1L; + + @Override + public WebMarkupContainer createPanel(String panelId) { + return new FocusTasksTabPanel<>(panelId, getMainForm(), getObjectModel(), + countFocusObjectTasks(parentPage) > 0); + } + + @Override + public String getCount() { + return Integer.toString(countFocusObjectTasks(parentPage)); + } + }); + + tabs.add( + new CountablePanelTab(parentPage.createStringResource("pageAdminFocus.triggers"), + getTabVisibility(ComponentConstants.UI_FOCUS_TAB_TASKS_URL, false, parentPage)){ + + private static final long serialVersionUID = 1L; + + @Override + public WebMarkupContainer createPanel(String panelId) { + return new FocusTriggersTabPanel<>(panelId, getMainForm(), getObjectModel()); + } + + @Override + public String getCount() { + return Integer.toString(countFocusObjectTriggers()); + } + }); + + } + + private int countFocusObjectTasks(PageBase parentPage){ + String oid; + if (getObjectWrapper() == null || StringUtils.isEmpty(getObjectWrapper().getOid())) { + oid = "non-existent"; + } else { + oid = getObjectWrapper().getOid(); + } + ObjectQuery casesQuery = QueryUtils.filterForCasesOverUser(parentPage.getPrismContext().queryFor(CaseType.class), oid) + .desc(ItemPath.create(CaseType.F_METADATA, MetadataType.F_CREATE_TIMESTAMP)) + .build(); + return WebModelServiceUtils.countObjects(CaseType.class, casesQuery, parentPage); + } + + private int countFocusObjectTriggers(){ + PrismObjectWrapper objectWrapper = getObjectWrapper(); + if (objectWrapper.getObject() != null){ + F focusObject = objectWrapper.getObject().asObjectable(); + return focusObject.getTrigger() != null ? focusObject.getTrigger().size() : 0; + } + return 0; + } + + @Override + protected boolean areSavePreviewButtonsEnabled() { + PrismObjectWrapper focusWrapper = getObjectModel().getObject(); + PrismContainerWrapper assignmentsWrapper; + try { + assignmentsWrapper = focusWrapper.findContainer(FocusType.F_ASSIGNMENT); + } catch (SchemaException e) { + LOGGER.error("Cannot find assignment wrapper: {}", e.getMessage()); + return false; + } + return isAssignmentsModelChanged(assignmentsWrapper); + } + + protected boolean isAssignmentsModelChanged(PrismContainerWrapper assignmentsWrapper){ + if (assignmentsWrapper != null) { + for (PrismContainerValueWrapper assignmentWrapper : assignmentsWrapper.getValues()) { + if (ValueStatus.DELETED.equals(assignmentWrapper.getStatus()) || + ValueStatus.ADDED.equals(assignmentWrapper.getStatus())) { + return true; + } + } + } + return false; + } + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusPersonasTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusPersonasTabPanel.java index b8b911ea896..a7d053bf858 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusPersonasTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusPersonasTabPanel.java @@ -18,7 +18,7 @@ import com.evolveum.midpoint.gui.api.GuiStyleConstants; import com.evolveum.midpoint.gui.api.component.MainObjectListPanel; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; import com.evolveum.midpoint.prism.PrismObject; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusProjectionsTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusProjectionsTabPanel.java index 98bf4ef2411..cefa473cd5e 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusProjectionsTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusProjectionsTabPanel.java @@ -8,12 +8,9 @@ import java.util.ArrayList; import java.util.List; - import javax.xml.namespace.QName; -import com.evolveum.midpoint.model.api.AssignmentObjectRelation; -import com.evolveum.midpoint.web.component.search.SearchFactory; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import com.evolveum.midpoint.gui.impl.prism.panel.ShadowPanel; import org.apache.commons.lang.Validate; import org.apache.wicket.Component; @@ -21,7 +18,6 @@ import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.list.ListItem; -import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.PropertyModel; @@ -33,40 +29,34 @@ import com.evolveum.midpoint.gui.api.component.DisplayNamePanel; import com.evolveum.midpoint.gui.api.component.ObjectBrowserPanel; import com.evolveum.midpoint.gui.api.component.PendingOperationPanel; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.page.PageBase; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.api.prism.ShadowWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ShadowWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; import com.evolveum.midpoint.gui.impl.component.MultivalueContainerDetailsPanel; import com.evolveum.midpoint.gui.impl.component.MultivalueContainerListPanelWithDetailsPanel; import com.evolveum.midpoint.gui.impl.component.ProjectionDisplayNamePanel; +import com.evolveum.midpoint.gui.impl.component.data.column.AbstractItemWrapperColumn.ColumnType; +import com.evolveum.midpoint.gui.impl.component.data.column.CompositedIconColumn; +import com.evolveum.midpoint.gui.impl.component.data.column.PrismContainerWrapperColumn; import com.evolveum.midpoint.gui.impl.component.data.column.PrismPropertyWrapperColumn; import com.evolveum.midpoint.gui.impl.component.data.column.PrismReferenceWrapperColumn; -import com.evolveum.midpoint.gui.impl.component.data.column.AbstractItemWrapperColumn.ColumnType; import com.evolveum.midpoint.gui.impl.component.icon.CompositedIcon; import com.evolveum.midpoint.gui.impl.component.icon.CompositedIconBuilder; -import com.evolveum.midpoint.gui.impl.component.data.column.CompositedIconColumn; -import com.evolveum.midpoint.gui.impl.component.data.column.PrismContainerWrapperColumn; -import com.evolveum.midpoint.gui.impl.factory.ItemRealValueModel; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismObjectValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.ShadowPanel; -import com.evolveum.midpoint.prism.PrismContainerDefinition; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectDefinition; -import com.evolveum.midpoint.prism.PrismPropertyDefinition; -import com.evolveum.midpoint.prism.PrismPropertyValue; -import com.evolveum.midpoint.prism.PrismReferenceDefinition; -import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.gui.impl.factory.panel.ItemRealValueModel; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; +import com.evolveum.midpoint.model.api.AssignmentObjectRelation; +import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.result.OperationResult; @@ -84,12 +74,14 @@ import com.evolveum.midpoint.web.component.menu.cog.ButtonInlineMenuItem; import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItem; import com.evolveum.midpoint.web.component.menu.cog.InlineMenuItemAction; +import com.evolveum.midpoint.web.component.search.SearchFactory; import com.evolveum.midpoint.web.component.search.SearchItemDefinition; import com.evolveum.midpoint.web.page.admin.PageAdminFocus; import com.evolveum.midpoint.web.page.admin.users.dto.UserDtoStatus; import com.evolveum.midpoint.web.session.PageStorage; import com.evolveum.midpoint.web.session.UserProfileStorage; import com.evolveum.midpoint.web.session.UserProfileStorage.TableId; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; /** * @author semancik @@ -268,17 +260,19 @@ protected DisplayNamePanel createDisplayNamePanel(String displayName @Override protected void addBasicContainerValuePanel(String idPanel) { - add(new WebMarkupContainer(idPanel)); + ShadowPanel shadowPanel = new ShadowPanel(idPanel, getParentModel(getModel())); + add(shadowPanel); +// add(new WebMarkupContainer(idPanel)); } - @Override - protected WebMarkupContainer getSpecificContainers(String contentAreaId) { - Fragment specificContainers = new Fragment(contentAreaId, ID_SPECIFIC_CONTAINERS_FRAGMENT, FocusProjectionsTabPanel.this); - - ShadowPanel shadowPanel = new ShadowPanel(ID_SHADOW_PANEL, getParentModel(getModel())); - specificContainers.add(shadowPanel); - return specificContainers; - } +// @Override +// protected WebMarkupContainer getSpecificContainers(String contentAreaId) { +// Fragment specificContainers = new Fragment(contentAreaId, ID_SPECIFIC_CONTAINERS_FRAGMENT, FocusProjectionsTabPanel.this); +// +// ShadowPanel shadowPanel = new ShadowPanel(ID_SHADOW_PANEL, getParentModel(getModel())); +// specificContainers.add(shadowPanel); +// return specificContainers; +// } }; return detailsPanel; } @@ -342,6 +336,9 @@ public String getCssClass() @Override protected Component createColumnPanel(String componentId, IModel rowModel) { IW object = rowModel.getObject(); + if (object == null) { + return new WebMarkupContainer(componentId); + } List> values = object.getValues(); List pendingOperations = new ArrayList(); values.forEach(value -> { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusTasksTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusTasksTabPanel.java index 6553b28d30d..3222fdb260a 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusTasksTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusTasksTabPanel.java @@ -17,7 +17,7 @@ import org.apache.wicket.markup.html.basic.Label; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.component.form.Form; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusTriggersTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusTriggersTabPanel.java index 1b1083a01ea..250550c8010 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusTriggersTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/FocusTriggersTabPanel.java @@ -7,15 +7,14 @@ package com.evolveum.midpoint.web.component.objectdetails; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.impl.component.MultivalueContainerListPanel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.model.api.AssignmentObjectRelation; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.web.component.DateLabelComponent; -import com.evolveum.midpoint.web.component.data.column.LinkColumn; import com.evolveum.midpoint.web.component.form.Form; import com.evolveum.midpoint.web.component.search.SearchItemDefinition; import com.evolveum.midpoint.web.component.util.VisibleBehaviour; @@ -29,9 +28,7 @@ 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.xml.namespace.QName; import java.util.ArrayList; import java.util.List; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/ObjectHistoryTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/ObjectHistoryTabPanel.java index 6549772150a..f7cb36567a5 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/ObjectHistoryTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/ObjectHistoryTabPanel.java @@ -21,7 +21,7 @@ import com.evolveum.midpoint.gui.api.GuiStyleConstants; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; import com.evolveum.midpoint.prism.PrismContext; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/UserDelegationsTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/UserDelegationsTabPanel.java index 1db6ea238c4..f6ad57194e6 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/UserDelegationsTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/objectdetails/UserDelegationsTabPanel.java @@ -19,7 +19,7 @@ import com.evolveum.midpoint.gui.api.component.ObjectBrowserPanel; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.query.ObjectFilter; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/DynamicFieldGroupPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/DynamicFieldGroupPanel.java index 4c1b0cdba3d..58c17bf4cf7 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/DynamicFieldGroupPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/DynamicFieldGroupPanel.java @@ -20,9 +20,9 @@ import com.evolveum.midpoint.gui.api.component.BasePanel; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyPanel; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.gui.impl.prism.panel.PrismPropertyPanel; import com.evolveum.midpoint.gui.impl.util.GuiImplUtil; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.MutableItemDefinition; @@ -90,7 +90,7 @@ private void initLayout(String groupName, List formItems, continue; } - ItemWrapper itemWrapper = findAndTailorItemWrapper(formItem, getObjectWrapper()); + ItemWrapper itemWrapper = findAndTailorItemWrapper(formItem, getObjectWrapper()); try { Panel panel = getPageBase().initItemPanel(itemView.newChildId(), itemWrapper.getTypeName(), Model.of(itemWrapper), null); @@ -108,14 +108,14 @@ private RepeatingView getRepeatingPropertyView() { } @NotNull - private ItemWrapper findAndTailorItemWrapper(AbstractFormItemType formField, PrismObjectWrapper objectWrapper) { - ItemWrapper itemWrapper = findItemWrapper(formField, objectWrapper); + private ItemWrapper findAndTailorItemWrapper(AbstractFormItemType formField, PrismObjectWrapper objectWrapper) { + ItemWrapper itemWrapper = findItemWrapper(formField, objectWrapper); applyFormDefinition(itemWrapper, formField); return itemWrapper; } @NotNull - private ItemWrapper findItemWrapper(AbstractFormItemType formField, PrismObjectWrapper objectWrapper) { + private ItemWrapper findItemWrapper(AbstractFormItemType formField, PrismObjectWrapper objectWrapper) { ItemPath path = GuiImplUtil.getItemPath(formField); if (path == null) { getSession().error("Bad form item definition. It has to contain reference to the real attribute"); @@ -123,8 +123,7 @@ private RepeatingView getRepeatingPropertyView() { throw new RestartResponseException(getPageBase()); } - ItemWrapper itemWrapper; - ItemDefinition itemDef = objectWrapper.getObject().getDefinition().findItemDefinition(path); + ItemWrapper itemWrapper; try { itemWrapper = objectWrapper.findItem(path, ItemWrapper.class); } catch (SchemaException e) { @@ -141,7 +140,7 @@ private RepeatingView getRepeatingPropertyView() { return itemWrapper; } - private void applyFormDefinition(ItemWrapper itemWrapper, AbstractFormItemType formField) { + private void applyFormDefinition(ItemWrapper itemWrapper, AbstractFormItemType formField) { FormItemDisplayType displayType = formField.getDisplay(); @@ -182,7 +181,7 @@ public boolean checkRequiredFields(PageBase pageBase) { if (component instanceof PrismPropertyPanel) { IModel model = component.getDefaultModel(); if (model != null && model.getObject() instanceof ItemWrapper) { - ItemWrapper itemWrapper = (ItemWrapper) model.getObject(); + ItemWrapper itemWrapper = (ItemWrapper) model.getObject(); if (!itemWrapper.checkRequired(pageBase)) { rvHolder.setValue(false); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/DynamicFormPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/DynamicFormPanel.java index 35c9cb2ef70..bd7a9e708d3 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/DynamicFormPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/DynamicFormPanel.java @@ -22,10 +22,10 @@ import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.page.PageBase; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.gui.impl.util.GuiImplUtil; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismObjectDefinition; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/InputPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/InputPanel.java index e9ba1a4ebcd..99013165a52 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/InputPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/InputPanel.java @@ -8,9 +8,15 @@ package com.evolveum.midpoint.web.component.prism; import com.evolveum.midpoint.gui.api.Validatable; + +import org.apache.wicket.Component; +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; +import org.apache.wicket.behavior.Behavior; import org.apache.wicket.markup.html.form.FormComponent; import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -21,6 +27,10 @@ public abstract class InputPanel extends Panel implements Validatable { private static final long serialVersionUID = 1L; + private List behaviors = new ArrayList<>(); + private IModel label; + private boolean required; + public InputPanel(String id) { super(id); } @@ -35,4 +45,28 @@ public List getFormComponents() { public FormComponent getValidatableComponent() { return getBaseFormComponent(); } + + public void append(Behavior behavior) { + behaviors.add(behavior); + } + + public void setComponentLabel(IModel label) { + this.label = label; + } + + public void required(boolean required) { + this.required = required; + } + + // @Override +// protected void onConfigure() { +// super.onConfigure(); +// for (FormComponent formComponent : getFormComponents()) { +// formComponent.add(behaviors.toArray(new Behavior[]{})); +// formComponent.setRequired(required); +// formComponent.setLabel(label); +// } +// +// } + } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ItemVisibility.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ItemVisibility.java index de153957f74..83158a1e715 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ItemVisibility.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/prism/ItemVisibility.java @@ -12,11 +12,6 @@ */ public enum ItemVisibility { - /** - * Element always visible. - */ - VISIBLE, - /** * Visibility determined automatically (e.g. based on "show empty" button). */ diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/progress/StatisticsDtoModel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/progress/StatisticsDtoModel.java index 4e8e9800c60..4e694f5170e 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/progress/StatisticsDtoModel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/progress/StatisticsDtoModel.java @@ -1,105 +1,105 @@ -/* - * Copyright (c) 2010-2015 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.web.component.progress; - -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -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.xml.ns._public.common.common_3.EnvironmentalPerformanceInformationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationStatsType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; -import org.apache.wicket.model.IModel; - -/** - * @author Pavol Mederly - */ -public class StatisticsDtoModel implements IModel { - - private static final Trace LOGGER = TraceManager.getTrace(StatisticsDtoModel.class); - - // at most one of these may be null - private transient Task task; - private IModel> taskModel; - - private transient StatisticsDto cachedObject; - - public StatisticsDtoModel() { - } - - public StatisticsDtoModel(IModel> taskModel) { - this.taskModel = taskModel; - } - - @Override - public StatisticsDto getObject() { - //we can't use cache here probably because data on the panel - // should be updated all the time -// if (cachedObject != null) { -// return cachedObject; -// } - - StatisticsDto info = getObjectInternal(); - if (info != null) { - cachedObject = info; - return cachedObject; - } - - return new StatisticsDto(); - } - - public StatisticsDto getObjectInternal() { - - if (task != null) { - return getStatisticsFromTask(task); - } - if (taskModel != null && taskModel.getObject() != null && taskModel.getObject().getObject() != null) { - return getStatisticsFromTaskType(taskModel.getObject().getObject().asObjectable()); - } - return null; - } - - protected StatisticsDto getStatisticsFromTask(Task task) { - - OperationStatsType operationStats = task.getAggregatedLiveOperationStats(); - if (operationStats == null) { - LOGGER.warn("No operational information in task"); - return null; - } - EnvironmentalPerformanceInformationType envInfo = operationStats.getEnvironmentalPerformanceInformation(); - if (envInfo == null) { - LOGGER.warn("No environmental performance information in task"); - return null; - } - StatisticsDto dto = new StatisticsDto(envInfo); - return dto; - } - - protected StatisticsDto getStatisticsFromTaskType(TaskType task) { - OperationStatsType operationStats = task.getOperationStats(); - if (operationStats == null) { - LOGGER.warn("No operational information in task"); - return null; - } - EnvironmentalPerformanceInformationType envInfo = operationStats.getEnvironmentalPerformanceInformation(); - if (envInfo == null) { - LOGGER.warn("No environmental performance information in task"); - return null; - } - StatisticsDto dto = new StatisticsDto(envInfo); - return dto; - } - - public void setTask(Task task) { - this.task = task; - } - - public void invalidateCache() { - cachedObject = null; - } -} +/* + * Copyright (c) 2010-2015 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.web.component.progress; + +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +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.xml.ns._public.common.common_3.EnvironmentalPerformanceInformationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationStatsType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; +import org.apache.wicket.model.IModel; + +/** + * @author Pavol Mederly + */ +public class StatisticsDtoModel implements IModel { + + private static final Trace LOGGER = TraceManager.getTrace(StatisticsDtoModel.class); + + // at most one of these may be null + private transient Task task; + private IModel> taskModel; + + private transient StatisticsDto cachedObject; + + public StatisticsDtoModel() { + } + + public StatisticsDtoModel(IModel> taskModel) { + this.taskModel = taskModel; + } + + @Override + public StatisticsDto getObject() { + //we can't use cache here probably because data on the panel + // should be updated all the time +// if (cachedObject != null) { +// return cachedObject; +// } + + StatisticsDto info = getObjectInternal(); + if (info != null) { + cachedObject = info; + return cachedObject; + } + + return new StatisticsDto(); + } + + public StatisticsDto getObjectInternal() { + + if (task != null) { + return getStatisticsFromTask(task); + } + if (taskModel != null && taskModel.getObject() != null && taskModel.getObject().getObject() != null) { + return getStatisticsFromTaskType(taskModel.getObject().getObject().asObjectable()); + } + return null; + } + + protected StatisticsDto getStatisticsFromTask(Task task) { + + OperationStatsType operationStats = task.getAggregatedLiveOperationStats(); + if (operationStats == null) { + LOGGER.warn("No operational information in task"); + return null; + } + EnvironmentalPerformanceInformationType envInfo = operationStats.getEnvironmentalPerformanceInformation(); + if (envInfo == null) { + LOGGER.warn("No environmental performance information in task"); + return null; + } + StatisticsDto dto = new StatisticsDto(envInfo); + return dto; + } + + protected StatisticsDto getStatisticsFromTaskType(TaskType task) { + OperationStatsType operationStats = task.getOperationStats(); + if (operationStats == null) { + LOGGER.warn("No operational information in task"); + return null; + } + EnvironmentalPerformanceInformationType envInfo = operationStats.getEnvironmentalPerformanceInformation(); + if (envInfo == null) { + LOGGER.warn("No environmental performance information in task"); + return null; + } + StatisticsDto dto = new StatisticsDto(envInfo); + return dto; + } + + public void setTask(Task task) { + this.task = task; + } + + public void invalidateCache() { + cachedObject = null; + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/sample/HelloObjectTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/sample/HelloObjectTabPanel.java index b99b3c9b6d2..bf2a98b09b0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/sample/HelloObjectTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/sample/HelloObjectTabPanel.java @@ -10,7 +10,7 @@ import org.apache.wicket.model.Model; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.web.component.form.Form; import com.evolveum.midpoint.web.component.objectdetails.AbstractObjectTabPanel; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/sample/SampleFormFocusTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/sample/SampleFormFocusTabPanel.java index 579cb43f765..042dc9fa4cf 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/sample/SampleFormFocusTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/sample/SampleFormFocusTabPanel.java @@ -14,8 +14,8 @@ import org.apache.wicket.markup.html.basic.Label; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.api.prism.ShadowWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ShadowWrapper; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.exception.CommunicationException; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/ContainerListDataProvider.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/ContainerListDataProvider.java index c562505a831..1258478e08a 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/ContainerListDataProvider.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/ContainerListDataProvider.java @@ -7,12 +7,10 @@ package com.evolveum.midpoint.web.component.util; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.api.util.WebPrismUtil; -import com.evolveum.midpoint.gui.impl.factory.PrismContainerWrapperFactoryImpl; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.impl.factory.wrapper.PrismContainerWrapperFactoryImpl; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.prism.Containerable; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.query.ObjectPaging; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.schema.GetOperationOptions; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/MultivalueContainerListDataProvider.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/MultivalueContainerListDataProvider.java index cd14ba597af..b0e8e7514d0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/MultivalueContainerListDataProvider.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/util/MultivalueContainerListDataProvider.java @@ -22,7 +22,7 @@ import org.apache.wicket.model.IModel; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.util.exception.SchemaException; 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 3c4ed42c6bd..2acb0f40033 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 @@ -10,27 +10,24 @@ import java.util.*; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapperImpl; +import com.evolveum.midpoint.gui.impl.prism.panel.SingleContainerPanel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.prism.*; -import com.evolveum.midpoint.prism.delta.ChangeType; import com.evolveum.midpoint.prism.delta.ContainerDelta; import org.apache.wicket.RestartResponseException; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.extensions.markup.html.tabs.AbstractTab; import org.apache.wicket.extensions.markup.html.tabs.ITab; import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; -import org.jetbrains.annotations.NotNull; import com.evolveum.midpoint.gui.api.model.NonEmptyLoadableModel; import com.evolveum.midpoint.gui.api.page.PageBase; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.schema.PrismSchema; @@ -169,13 +166,12 @@ public boolean isVisible() { } private List createConfigurationTabs() { - final com.evolveum.midpoint.web.component.form.Form form = getForm(); List tabs = new ArrayList<>(); PrismContainerWrapper configuration = configurationModel.getObject(); if (configuration == null) { return new ArrayList<>(); } - PrismContainerValueWrapper configurationValue = null; + PrismContainerValueWrapper configurationValue; try { configurationValue = configuration.getValue(); } catch (SchemaException e) { @@ -190,13 +186,7 @@ private List createConfigurationTabs() { @Override public WebMarkupContainer getPanel(String panelId) { - try { - return getPageBase().initItemPanel(panelId, wrapper.getTypeName(), Model.of(wrapper), null); - } catch (SchemaException e) { - LOGGER.error("Cannot create panel for {}, reason: {}", wrapper.getTypeName(), e.getMessage(), e); - getSession().error("Cannot create panel for " + wrapper.getTypeName() + ", reason: " + e.getMessage()); - return null; - } + return new SingleContainerPanel<>(panelId, Model.of(wrapper), wrapper.getTypeName()); } }); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/AbstractWrapperModel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/AbstractWrapperModel.java index e6e79e9b7e3..c1201176410 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/AbstractWrapperModel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/AbstractWrapperModel.java @@ -10,7 +10,7 @@ import org.apache.commons.lang.Validate; import org.apache.wicket.model.IModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/ContainerValueWrapperFromObjectWrapperModel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/ContainerValueWrapperFromObjectWrapperModel.java index 7e84e32519b..701b7b308a2 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/ContainerValueWrapperFromObjectWrapperModel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/ContainerValueWrapperFromObjectWrapperModel.java @@ -10,15 +10,13 @@ import org.apache.commons.lang.Validate; import org.apache.wicket.model.IModel; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; /** * Model that returns property real values. This implementation works on ObjectWrapper models (not PrismObject). diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/ContainerWrapperFromObjectWrapperModel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/ContainerWrapperFromObjectWrapperModel.java index 3ba324cad64..eed779a93aa 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/ContainerWrapperFromObjectWrapperModel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/ContainerWrapperFromObjectWrapperModel.java @@ -12,9 +12,9 @@ import org.apache.commons.lang.Validate; import org.apache.wicket.model.IModel; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.util.logging.Trace; @@ -57,7 +57,7 @@ public PrismContainerWrapper getObject() { } @Override - public void setObject(com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper arg0) { + public void setObject(PrismContainerWrapper arg0) { throw new UnsupportedOperationException("ContainerWrapperFromObjectWrapperModel.setObject called"); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/ItemWrapperModel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/ItemWrapperModel.java index 3c358a95f0f..1c54c5654db 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/ItemWrapperModel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/ItemWrapperModel.java @@ -10,10 +10,10 @@ import com.evolveum.midpoint.gui.api.page.PageBase; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.Item; import com.evolveum.midpoint.prism.ItemDefinition; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismContainerWrapperHeaderModel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismContainerWrapperHeaderModel.java index bd3c34b6187..b66b086624a 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismContainerWrapperHeaderModel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismContainerWrapperHeaderModel.java @@ -9,9 +9,8 @@ import org.apache.wicket.model.IModel; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; import com.evolveum.midpoint.prism.Containerable; -import com.evolveum.midpoint.prism.PrismContainer; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.path.ItemPath; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismContainerWrapperModel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismContainerWrapperModel.java index 12ef8d87cf1..a828cef94b1 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismContainerWrapperModel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismContainerWrapperModel.java @@ -8,8 +8,8 @@ import org.apache.wicket.model.IModel; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.path.ItemName; import com.evolveum.midpoint.prism.path.ItemPath; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismPropertyWrapperHeaderModel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismPropertyWrapperHeaderModel.java index dc246733198..7783dac3aa5 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismPropertyWrapperHeaderModel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismPropertyWrapperHeaderModel.java @@ -9,9 +9,8 @@ import org.apache.wicket.model.IModel; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; import com.evolveum.midpoint.prism.Containerable; -import com.evolveum.midpoint.prism.PrismProperty; import com.evolveum.midpoint.prism.PrismPropertyDefinition; import com.evolveum.midpoint.prism.path.ItemPath; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismPropertyWrapperModel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismPropertyWrapperModel.java index 7b12fc7594a..4053d8202e3 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismPropertyWrapperModel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismPropertyWrapperModel.java @@ -8,9 +8,9 @@ import org.apache.wicket.model.IModel; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.path.ItemName; import com.evolveum.midpoint.prism.path.ItemPath; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismReferenceWrapperHeaderModel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismReferenceWrapperHeaderModel.java index 1497e6c6d40..9f15fa00d2d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismReferenceWrapperHeaderModel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismReferenceWrapperHeaderModel.java @@ -9,10 +9,8 @@ import org.apache.wicket.model.IModel; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismReferenceWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismReferenceWrapper; import com.evolveum.midpoint.prism.Containerable; -import com.evolveum.midpoint.prism.PrismReference; import com.evolveum.midpoint.prism.PrismReferenceDefinition; import com.evolveum.midpoint.prism.Referencable; import com.evolveum.midpoint.prism.path.ItemPath; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismReferenceWrapperModel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismReferenceWrapperModel.java index 9699d8f8ab0..bf8ebd60878 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismReferenceWrapperModel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/model/PrismReferenceWrapperModel.java @@ -8,9 +8,9 @@ import org.apache.wicket.model.IModel; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismReferenceWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismReferenceWrapper; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.Referencable; import com.evolveum.midpoint.prism.path.ItemName; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/PageAdminFocus.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/PageAdminFocus.java index f0eefc2edb8..0afbf0b14d0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/PageAdminFocus.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/PageAdminFocus.java @@ -16,13 +16,13 @@ import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.api.prism.ShadowWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ShadowWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; -import com.evolveum.midpoint.gui.impl.prism.PrismObjectValueWrapper; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectValueWrapper; import com.evolveum.midpoint.model.api.ModelExecuteOptions; import com.evolveum.midpoint.model.api.context.*; import com.evolveum.midpoint.prism.*; 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 1e2a14bab76..4868adbc1ca 100755 --- 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 @@ -13,11 +13,9 @@ import com.evolveum.midpoint.gui.api.component.*; import com.evolveum.midpoint.gui.api.component.tabs.PanelTab; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.util.WebPrismUtil; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; import com.evolveum.midpoint.model.api.context.ModelContext; import com.evolveum.midpoint.prism.PrismContainer; -import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.schema.ObjectDeltaOperation; @@ -26,7 +24,6 @@ import com.evolveum.midpoint.util.MiscUtil; import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.web.component.AjaxButton; -import com.evolveum.midpoint.web.component.prism.ValueStatus; import com.evolveum.midpoint.web.component.prism.show.PagePreviewChanges; import com.evolveum.midpoint.web.component.refresh.Refreshable; import com.evolveum.midpoint.web.component.util.SelectableBean; @@ -60,11 +57,11 @@ import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.model.api.ModelExecuteOptions; import com.evolveum.midpoint.model.api.authentication.CompiledGuiProfile; import com.evolveum.midpoint.prism.PrismObject; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/archetype/PageArchetype.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/archetype/PageArchetype.java index f20e5d3a575..0d59d66abad 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/archetype/PageArchetype.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/archetype/PageArchetype.java @@ -1,127 +1,125 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.page.admin.archetype; - -import java.util.List; - -import org.apache.wicket.Page; -import org.apache.wicket.extensions.markup.html.tabs.ITab; -import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.model.IModel; -import org.apache.wicket.model.Model; -import org.apache.wicket.model.PropertyModel; -import org.apache.wicket.request.mapper.parameter.PageParameters; - -import com.evolveum.midpoint.gui.api.ComponentConstants; -import com.evolveum.midpoint.gui.api.component.tabs.PanelTab; -import com.evolveum.midpoint.gui.impl.page.admin.configuration.component.ContainerOfSystemConfigurationPanel; -import com.evolveum.midpoint.gui.impl.prism.PrismObjectValueWrapper; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.security.api.AuthorizationConstants; -import com.evolveum.midpoint.web.application.AuthorizationAction; -import com.evolveum.midpoint.web.application.PageDescriptor; -import com.evolveum.midpoint.web.component.ObjectSummaryPanel; -import com.evolveum.midpoint.web.component.objectdetails.AbstractObjectMainPanel; -import com.evolveum.midpoint.web.component.objectdetails.AbstractRoleMainPanel; -import com.evolveum.midpoint.web.model.PrismContainerWrapperModel; -import com.evolveum.midpoint.web.page.admin.PageAdminAbstractRole; -import com.evolveum.midpoint.web.page.admin.PageAdminObjectDetails; -import com.evolveum.midpoint.web.page.admin.roles.AbstractRoleMemberPanel; -import com.evolveum.midpoint.web.util.OnePageParameterEncoder; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ArchetypePolicyType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ArchetypeType; - -@PageDescriptor( - url = "/admin/archetype", - encoder = OnePageParameterEncoder.class, - action = { - @AuthorizationAction(actionUri = AuthorizationConstants.AUTZ_UI_ARCHETYPES_ALL_URL, - label = "PageArchetypes.auth.archetypesAll.label", - description = "PageArchetypes.auth.archetypesAll.description"), - @AuthorizationAction(actionUri = AuthorizationConstants.AUTZ_UI_ARCHETYPE_URL, - label = "PageArchetype.auth.user.label", - description = "PageArchetype.auth.archetype.description") - }) -public class PageArchetype extends PageAdminAbstractRole { - - private static final long serialVersionUID = 1L; - - public PageArchetype() { - super(); - } - - public PageArchetype(PageParameters parameters) { - super(parameters); - } - - public PageArchetype(final PrismObject role) { - super(role); - } - - public PageArchetype(final PrismObject userToEdit, boolean isNewObject) { - super(userToEdit, isNewObject); - } - - public PageArchetype(final PrismObject abstractRole, boolean isNewObject, boolean isReadonly) { - super(abstractRole, isNewObject, isReadonly); - } - - - @Override - public Class getCompileTimeClass() { - return ArchetypeType.class; - } - - @Override - protected ArchetypeType createNewObject() { - return new ArchetypeType(getPrismContext()); - } - - @Override - protected ObjectSummaryPanel createSummaryPanel(IModel summaryModel) { - return new ArchetypeSummaryPanel(ID_SUMMARY_PANEL, summaryModel, this); - - } - - @Override - protected AbstractObjectMainPanel createMainPanel(String id) { - return new AbstractRoleMainPanel(id, getObjectModel(), getProjectionModel(), this) { - - private static final long serialVersionUID = 1L; - - @Override - public AbstractRoleMemberPanel createMemberPanel(String panelId) { - return new ArchetypeMembersPanel(panelId, new Model<>(getObject().asObjectable())); - } - - @Override - protected List createTabs(PageAdminObjectDetails parentPage) { - List tabs = super.createTabs(parentPage); - tabs.add( - new PanelTab(parentPage.createStringResource("PageArchetype.archetypePolicy"), - getTabVisibility(ComponentConstants.UI_ARCHTYPE_TAB_ARCHETYPE_POLICY_URL, false, parentPage)) { - - private static final long serialVersionUID = 1L; - - @Override - public WebMarkupContainer createPanel(String panelId) { - return new ContainerOfSystemConfigurationPanel(panelId, PrismContainerWrapperModel.fromContainerWrapper(getObjectModel(), ArchetypeType.F_ARCHETYPE_POLICY), ArchetypePolicyType.COMPLEX_TYPE); - } - }); - - return tabs; - } - }; - - } - - @Override - protected Class getRestartResponsePage() { - return PageArchetypes.class; - } - -} +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.page.admin.archetype; + +import java.util.List; + +import org.apache.wicket.Page; +import org.apache.wicket.extensions.markup.html.tabs.ITab; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.request.mapper.parameter.PageParameters; + +import com.evolveum.midpoint.gui.api.ComponentConstants; +import com.evolveum.midpoint.gui.api.component.tabs.PanelTab; +import com.evolveum.midpoint.gui.impl.page.admin.configuration.component.ContainerOfSystemConfigurationPanel; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.security.api.AuthorizationConstants; +import com.evolveum.midpoint.web.application.AuthorizationAction; +import com.evolveum.midpoint.web.application.PageDescriptor; +import com.evolveum.midpoint.web.component.ObjectSummaryPanel; +import com.evolveum.midpoint.web.component.objectdetails.AbstractObjectMainPanel; +import com.evolveum.midpoint.web.component.objectdetails.AbstractRoleMainPanel; +import com.evolveum.midpoint.web.model.PrismContainerWrapperModel; +import com.evolveum.midpoint.web.page.admin.PageAdminAbstractRole; +import com.evolveum.midpoint.web.page.admin.PageAdminObjectDetails; +import com.evolveum.midpoint.web.page.admin.roles.AbstractRoleMemberPanel; +import com.evolveum.midpoint.web.util.OnePageParameterEncoder; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ArchetypePolicyType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ArchetypeType; + +@PageDescriptor( + url = "/admin/archetype", + encoder = OnePageParameterEncoder.class, + action = { + @AuthorizationAction(actionUri = AuthorizationConstants.AUTZ_UI_ARCHETYPES_ALL_URL, + label = "PageArchetypes.auth.archetypesAll.label", + description = "PageArchetypes.auth.archetypesAll.description"), + @AuthorizationAction(actionUri = AuthorizationConstants.AUTZ_UI_ARCHETYPE_URL, + label = "PageArchetype.auth.user.label", + description = "PageArchetype.auth.archetype.description") + }) +public class PageArchetype extends PageAdminAbstractRole { + + private static final long serialVersionUID = 1L; + + public PageArchetype() { + super(); + } + + public PageArchetype(PageParameters parameters) { + super(parameters); + } + + public PageArchetype(final PrismObject role) { + super(role); + } + + public PageArchetype(final PrismObject userToEdit, boolean isNewObject) { + super(userToEdit, isNewObject); + } + + public PageArchetype(final PrismObject abstractRole, boolean isNewObject, boolean isReadonly) { + super(abstractRole, isNewObject, isReadonly); + } + + + @Override + public Class getCompileTimeClass() { + return ArchetypeType.class; + } + + @Override + protected ArchetypeType createNewObject() { + return new ArchetypeType(getPrismContext()); + } + + @Override + protected ObjectSummaryPanel createSummaryPanel(IModel summaryModel) { + return new ArchetypeSummaryPanel(ID_SUMMARY_PANEL, summaryModel, this); + + } + + @Override + protected AbstractObjectMainPanel createMainPanel(String id) { + return new AbstractRoleMainPanel(id, getObjectModel(), getProjectionModel(), this) { + + private static final long serialVersionUID = 1L; + + @Override + public AbstractRoleMemberPanel createMemberPanel(String panelId) { + return new ArchetypeMembersPanel(panelId, new Model<>(getObject().asObjectable())); + } + + @Override + protected List createTabs(PageAdminObjectDetails parentPage) { + List tabs = super.createTabs(parentPage); + tabs.add( + new PanelTab(parentPage.createStringResource("PageArchetype.archetypePolicy"), + getTabVisibility(ComponentConstants.UI_ARCHTYPE_TAB_ARCHETYPE_POLICY_URL, false, parentPage)) { + + private static final long serialVersionUID = 1L; + + @Override + public WebMarkupContainer createPanel(String panelId) { + return new ContainerOfSystemConfigurationPanel(panelId, PrismContainerWrapperModel.fromContainerWrapper(getObjectModel(), ArchetypeType.F_ARCHETYPE_POLICY), ArchetypePolicyType.COMPLEX_TYPE); + } + }); + + return tabs; + } + }; + + } + + @Override + protected Class getRestartResponsePage() { + return PageArchetypes.class; + } + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/ApprovalCaseTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/ApprovalCaseTabPanel.java index 8f8074feff1..13a443324ec 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/ApprovalCaseTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/ApprovalCaseTabPanel.java @@ -8,7 +8,7 @@ import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.schema.util.ApprovalContextUtil; import com.evolveum.midpoint.schema.util.CaseTypeUtil; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseEventsTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseEventsTabPanel.java index 41f781b616a..5bd0aced5ca 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseEventsTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseEventsTabPanel.java @@ -9,7 +9,6 @@ import java.util.ArrayList; import java.util.List; -import com.evolveum.midpoint.xml.ns._public.common.common_3.CaseWorkItemType; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator; import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn; @@ -22,10 +21,10 @@ import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.impl.component.MultivalueContainerListPanel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.gui.impl.session.ObjectTabStorage; import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.query.ObjectQuery; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkItemActionsPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkItemActionsPanel.java index 60c6bb6f809..ab258633b73 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkItemActionsPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkItemActionsPanel.java @@ -157,21 +157,12 @@ private void forwardPerformed(AjaxRequestTarget target) { protected void onSelectPerformed(AjaxRequestTarget target, UserType user) { PageBase pageBase = CaseWorkItemActionsPanel.this.getPageBase(); pageBase.hideMainPopup(target); - ConfirmationPanel confirmationPanel = new ConfirmationPanel(pageBase.getMainPopupBodyId(), - createStringResource("CaseWorkItemActionsPanel.forwardConfirmationMessage", user.getName().getOrig())){ - private static final long serialVersionUID = 1L; - - @Override - public void yesPerformed(AjaxRequestTarget target) { - forwardConfirmedPerformed(target, user); - } - - @Override - public StringResourceModel getTitle() { - return new StringResourceModel("CaseWorkItemActionsPanel.forwardConfirmationTitle"); - } - }; - pageBase.showMainPopup(confirmationPanel, target); + forwardConfirmedPerformed(target, user); + } + + @Override + protected IModel getWarningMessageModel(){ + return getPageBase().createStringResource("CaseWorkItemActionsPanel.forwardWarningMessage"); } }; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkItemListWithDetailsPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkItemListWithDetailsPanel.java index 2e9433ee7f8..d197cf1a089 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkItemListWithDetailsPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkItemListWithDetailsPanel.java @@ -1,277 +1,277 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.page.admin.cases; - -import com.evolveum.midpoint.gui.api.component.DisplayNamePanel; -import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.impl.component.MultivalueContainerDetailsPanel; -import com.evolveum.midpoint.gui.impl.component.MultivalueContainerListPanelWithDetailsPanel; -import com.evolveum.midpoint.gui.impl.factory.ItemRealValueModel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.session.ObjectTabStorage; -import com.evolveum.midpoint.prism.PrismContainerDefinition; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.schema.util.*; -import com.evolveum.midpoint.web.component.AjaxButton; -import com.evolveum.midpoint.web.component.breadcrumbs.Breadcrumb; -import com.evolveum.midpoint.web.component.breadcrumbs.BreadcrumbPageInstance; -import com.evolveum.midpoint.web.component.data.column.ColumnUtils; -import com.evolveum.midpoint.web.component.data.column.LinkColumn; -import com.evolveum.midpoint.web.component.search.SearchItemDefinition; -import com.evolveum.midpoint.web.component.util.VisibleBehaviour; -import com.evolveum.midpoint.web.page.admin.workflow.WorkItemDetailsPanel; -import com.evolveum.midpoint.web.session.PageStorage; -import com.evolveum.midpoint.web.session.UserProfileStorage; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; -import org.apache.commons.collections.CollectionUtils; -import org.apache.wicket.Component; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; -import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.markup.html.list.ListItem; -import org.apache.wicket.model.IModel; -import org.apache.wicket.model.Model; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by honchar - */ -public abstract class CaseWorkItemListWithDetailsPanel extends MultivalueContainerListPanelWithDetailsPanel { - - private static final long serialVersionUID = 1L; - - private static final String ID_CASE_WORK_ITEM_ACTIONS_PANEL = "caseWorkItemActionsPanel"; - private static final String ID_CANCEL_BUTTON = "cancelButton"; - private WorkItemDetailsPanel workItemDetails = null; - - public CaseWorkItemListWithDetailsPanel(String id, IModel> model, UserProfileStorage.TableId tableId, PageStorage pageStorage){ - super(id, model, tableId, pageStorage); - } - - @Override - protected void onInitialize(){ - super.onInitialize(); - AjaxButton cancelButton = new AjaxButton(ID_CANCEL_BUTTON, - createStringResource("MultivalueContainerListPanel.cancelButton")) { - private static final long serialVersionUID = 1L; - - @Override - public void onClick(AjaxRequestTarget ajaxRequestTarget) { - setItemDetailsVisible(false); - cancelItemDetailsPerformed(ajaxRequestTarget); - ajaxRequestTarget.add(CaseWorkItemListWithDetailsPanel.this); - ajaxRequestTarget.add(CaseWorkItemListWithDetailsPanel.this.getPageBase().getFeedbackPanel()); - } - }; - getDetailsPanelContainer().add(cancelButton); - - CaseWorkItemActionsPanel actionsPanel = new CaseWorkItemActionsPanel(ID_CASE_WORK_ITEM_ACTIONS_PANEL, - new LoadableModel() { - private static final long serialVersionUID = 1L; - - @Override - protected CaseWorkItemType load() { - return getDetailsPanelItemsList().size() > 0 ? getDetailsPanelItemsList().get(0).getRealValue() : null; - } - }){ - private static final long serialVersionUID = 1L; - - @Override - protected AbstractWorkItemOutputType getWorkItemOutput(boolean approved) { - String comment = workItemDetails != null ? workItemDetails.getApproverComment() : null; - byte[] evidence = workItemDetails != null ? workItemDetails.getWorkItemEvidence() : null; - return super.getWorkItemOutput(approved) - .comment(comment) - .evidence(evidence); - } - - @Override - protected WorkItemDelegationRequestType getDelegationRequest(UserType delegate) { - return super.getDelegationRequest(delegate) - .comment(workItemDetails != null ? workItemDetails.getApproverComment() : null); - } - - @Override - protected Component getCustomForm(){ - return workItemDetails != null ? workItemDetails.getCustomForm() : null; - } - - @Override - protected void afterActionFinished(AjaxRequestTarget target){ - Breadcrumb previousBreadcrumb = getPageBase().getPreviousBreadcrumb(); - if (previousBreadcrumb instanceof BreadcrumbPageInstance && - ((BreadcrumbPageInstance)previousBreadcrumb).getPage() instanceof PageCaseWorkItem){ - getPageBase().redirectBack(3); - } else { - getPageBase().redirectBack(); - } - } - }; - actionsPanel.setOutputMarkupId(true); - actionsPanel.add(new VisibleBehaviour(() -> { - CaseWorkItemType workItemSelected = getDetailsPanelItemsList().size() > 0 ? getDetailsPanelItemsList().get(0).getRealValue() : null; - return CaseWorkItemUtil.isCaseWorkItemNotClosed(workItemSelected); - })); - getDetailsPanelContainer().add(actionsPanel); - } - - @Override - protected void initPaging() { - getWorkitemsTabStorage().setPaging(getPrismContext().queryFactory() - .createPaging(0, ((int) CaseWorkItemListWithDetailsPanel.this.getPageBase().getItemsPerPage(getTableId())))); - } - - protected abstract UserProfileStorage.TableId getTableId(); - - @Override - protected abstract ObjectQuery createQuery(); - - @Override - protected boolean enableActionNewObject() { - return false; - } - - @Override - protected boolean isSearchEnabled(){ - return false; - } - - @Override - protected List, String>> createColumns() { - return getWorkItemColumns(); - } - - @Override - protected WebMarkupContainer getSearchPanel(String contentAreaId) { - return new WebMarkupContainer(contentAreaId); - } - - @Override - protected List> postSearch( - List> workItems) { - return workItems; - } - - @Override - protected boolean isButtonPanelVisible(){ - return false; - } - - @Override - protected List initSearchableItems(PrismContainerDefinition containerDef) { - List defs = new ArrayList<>(); - return defs; - } - - @Override - protected MultivalueContainerDetailsPanel getMultivalueContainerDetailsPanel( - ListItem> item) { - return createWorkItemDetailsPanel(item); - } - -// @Override -// public void itemDetailsPerformed(AjaxRequestTarget target, IModel> model){} - - private ObjectTabStorage getWorkitemsTabStorage(){ - return getPageBase().getSessionStorage().getCaseWorkitemsTabStorage(); - } - - private MultivalueContainerDetailsPanel createWorkItemDetailsPanel( - ListItem> item) { - MultivalueContainerDetailsPanel detailsPanel = new MultivalueContainerDetailsPanel(MultivalueContainerListPanelWithDetailsPanel.ID_ITEM_DETAILS, item.getModel()) { - - private static final long serialVersionUID = 1L; - - @Override - protected DisplayNamePanel createDisplayNamePanel(String displayNamePanelId) { - ItemRealValueModel displayNameModel = new ItemRealValueModel(item.getModel()); - return new DisplayNamePanel(displayNamePanelId, displayNameModel) { - private static final long serialVersionUID = 1L; - - @Override - protected IModel getDescriptionLabelModel() { - CaseType caseType = CaseWorkItemUtil.getCase(displayNameModel.getObject()); - return Model.of(caseType != null && caseType.getDescription() != null ? caseType.getDescription() : ""); - } - }; - } - - @Override - protected void addBasicContainerValuePanel(String idPanel) { - //todo fix implement with WorkItemDetailsPanelFactory - workItemDetails = new WorkItemDetailsPanel(idPanel, Model.of(item.getModel().getObject().getRealValue())); - workItemDetails.setOutputMarkupId(true); - add(workItemDetails); - } - - }; - return detailsPanel; - } - - - private List, String>> getWorkItemColumns(){ - List, String>> columns = new ArrayList<>(); - -// columns.add(new IconColumn>(Model.of("")) { -// -// private static final long serialVersionUID = 1L; -// -// @Override -// protected IModel createIconModel(IModel> rowModel) { -// return new IModel() { -// -// private static final long serialVersionUID = 1L; -// -// @Override -// public String getObject() { -// return WebComponentUtil.createDefaultBlackIcon(AssignmentsUtil.getTargetType(rowModel.getObject().getContainerValue().asContainerable())); -// } -// }; -// } -// -// }); - columns.add(new LinkColumn>(createStringResource("PolicyRulesPanel.nameColumn")){ - private static final long serialVersionUID = 1L; - - @Override - protected IModel createLinkModel(IModel> rowModel) { - PolyStringType workitemName = unwrapRowModel(rowModel).getName(); - return Model.of(WebComponentUtil.getTranslatedPolyString(workitemName)); - } - - @Override - public boolean isEnabled(IModel> rowModel) { - //TODO should we check any authorization? - return true; - } - - @Override - public void onClick(AjaxRequestTarget target, IModel> rowModel) { - CaseWorkItemListWithDetailsPanel.this.itemDetailsPerformed(target, rowModel); - - } - }); - - columns.addAll(ColumnUtils.getDefaultWorkItemColumns(getPageBase(), true)); - return columns; - } - - private CaseWorkItemType unwrapRowModel(IModel> rowModel){ - return rowModel.getObject().getRealValue(); - } - - private CaseWorkItemType unwrapPanelModel(){ - return getModelObject() != null && CollectionUtils.isNotEmpty(getModelObject().getValues()) ? - getModelObject().getValues().get(0).getRealValue() : null; - } - -} +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.page.admin.cases; + +import com.evolveum.midpoint.gui.api.component.DisplayNamePanel; +import com.evolveum.midpoint.gui.api.model.LoadableModel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.gui.impl.component.MultivalueContainerDetailsPanel; +import com.evolveum.midpoint.gui.impl.component.MultivalueContainerListPanelWithDetailsPanel; +import com.evolveum.midpoint.gui.impl.factory.panel.ItemRealValueModel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.impl.session.ObjectTabStorage; +import com.evolveum.midpoint.prism.PrismContainerDefinition; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.schema.util.*; +import com.evolveum.midpoint.web.component.AjaxButton; +import com.evolveum.midpoint.web.component.breadcrumbs.Breadcrumb; +import com.evolveum.midpoint.web.component.breadcrumbs.BreadcrumbPageInstance; +import com.evolveum.midpoint.web.component.data.column.ColumnUtils; +import com.evolveum.midpoint.web.component.data.column.LinkColumn; +import com.evolveum.midpoint.web.component.search.SearchItemDefinition; +import com.evolveum.midpoint.web.component.util.VisibleBehaviour; +import com.evolveum.midpoint.web.page.admin.workflow.WorkItemDetailsPanel; +import com.evolveum.midpoint.web.session.PageStorage; +import com.evolveum.midpoint.web.session.UserProfileStorage; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; +import org.apache.commons.collections.CollectionUtils; +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by honchar + */ +public abstract class CaseWorkItemListWithDetailsPanel extends MultivalueContainerListPanelWithDetailsPanel { + + private static final long serialVersionUID = 1L; + + private static final String ID_CASE_WORK_ITEM_ACTIONS_PANEL = "caseWorkItemActionsPanel"; + private static final String ID_CANCEL_BUTTON = "cancelButton"; + private WorkItemDetailsPanel workItemDetails = null; + + public CaseWorkItemListWithDetailsPanel(String id, IModel> model, UserProfileStorage.TableId tableId, PageStorage pageStorage){ + super(id, model, tableId, pageStorage); + } + + @Override + protected void onInitialize(){ + super.onInitialize(); + AjaxButton cancelButton = new AjaxButton(ID_CANCEL_BUTTON, + createStringResource("MultivalueContainerListPanel.cancelButton")) { + private static final long serialVersionUID = 1L; + + @Override + public void onClick(AjaxRequestTarget ajaxRequestTarget) { + setItemDetailsVisible(false); + cancelItemDetailsPerformed(ajaxRequestTarget); + ajaxRequestTarget.add(CaseWorkItemListWithDetailsPanel.this); + ajaxRequestTarget.add(CaseWorkItemListWithDetailsPanel.this.getPageBase().getFeedbackPanel()); + } + }; + getDetailsPanelContainer().add(cancelButton); + + CaseWorkItemActionsPanel actionsPanel = new CaseWorkItemActionsPanel(ID_CASE_WORK_ITEM_ACTIONS_PANEL, + new LoadableModel() { + private static final long serialVersionUID = 1L; + + @Override + protected CaseWorkItemType load() { + return getDetailsPanelItemsList().size() > 0 ? getDetailsPanelItemsList().get(0).getRealValue() : null; + } + }){ + private static final long serialVersionUID = 1L; + + @Override + protected AbstractWorkItemOutputType getWorkItemOutput(boolean approved) { + String comment = workItemDetails != null ? workItemDetails.getApproverComment() : null; + byte[] evidence = workItemDetails != null ? workItemDetails.getWorkItemEvidence() : null; + return super.getWorkItemOutput(approved) + .comment(comment) + .evidence(evidence); + } + + @Override + protected WorkItemDelegationRequestType getDelegationRequest(UserType delegate) { + return super.getDelegationRequest(delegate) + .comment(workItemDetails != null ? workItemDetails.getApproverComment() : null); + } + + @Override + protected Component getCustomForm(){ + return workItemDetails != null ? workItemDetails.getCustomForm() : null; + } + + @Override + protected void afterActionFinished(AjaxRequestTarget target){ + Breadcrumb previousBreadcrumb = getPageBase().getPreviousBreadcrumb(); + if (previousBreadcrumb instanceof BreadcrumbPageInstance && + ((BreadcrumbPageInstance)previousBreadcrumb).getPage() instanceof PageCaseWorkItem){ + getPageBase().redirectBack(3); + } else { + getPageBase().redirectBack(); + } + } + }; + actionsPanel.setOutputMarkupId(true); + actionsPanel.add(new VisibleBehaviour(() -> { + CaseWorkItemType workItemSelected = getDetailsPanelItemsList().size() > 0 ? getDetailsPanelItemsList().get(0).getRealValue() : null; + return CaseWorkItemUtil.isCaseWorkItemNotClosed(workItemSelected); + })); + getDetailsPanelContainer().add(actionsPanel); + } + + @Override + protected void initPaging() { + getWorkitemsTabStorage().setPaging(getPrismContext().queryFactory() + .createPaging(0, ((int) CaseWorkItemListWithDetailsPanel.this.getPageBase().getItemsPerPage(getTableId())))); + } + + protected abstract UserProfileStorage.TableId getTableId(); + + @Override + protected abstract ObjectQuery createQuery(); + + @Override + protected boolean enableActionNewObject() { + return false; + } + + @Override + protected boolean isSearchEnabled(){ + return false; + } + + @Override + protected List, String>> createColumns() { + return getWorkItemColumns(); + } + + @Override + protected WebMarkupContainer getSearchPanel(String contentAreaId) { + return new WebMarkupContainer(contentAreaId); + } + + @Override + protected List> postSearch( + List> workItems) { + return workItems; + } + + @Override + protected boolean isButtonPanelVisible(){ + return false; + } + + @Override + protected List initSearchableItems(PrismContainerDefinition containerDef) { + List defs = new ArrayList<>(); + return defs; + } + + @Override + protected MultivalueContainerDetailsPanel getMultivalueContainerDetailsPanel( + ListItem> item) { + return createWorkItemDetailsPanel(item); + } + +// @Override +// public void itemDetailsPerformed(AjaxRequestTarget target, IModel> model){} + + private ObjectTabStorage getWorkitemsTabStorage(){ + return getPageBase().getSessionStorage().getCaseWorkitemsTabStorage(); + } + + private MultivalueContainerDetailsPanel createWorkItemDetailsPanel( + ListItem> item) { + MultivalueContainerDetailsPanel detailsPanel = new MultivalueContainerDetailsPanel(MultivalueContainerListPanelWithDetailsPanel.ID_ITEM_DETAILS, item.getModel()) { + + private static final long serialVersionUID = 1L; + + @Override + protected DisplayNamePanel createDisplayNamePanel(String displayNamePanelId) { + ItemRealValueModel displayNameModel = new ItemRealValueModel(item.getModel()); + return new DisplayNamePanel(displayNamePanelId, displayNameModel) { + private static final long serialVersionUID = 1L; + + @Override + protected IModel getDescriptionLabelModel() { + CaseType caseType = CaseWorkItemUtil.getCase(displayNameModel.getObject()); + return Model.of(caseType != null && caseType.getDescription() != null ? caseType.getDescription() : ""); + } + }; + } + + @Override + protected void addBasicContainerValuePanel(String idPanel) { + //todo fix implement with WorkItemDetailsPanelFactory + workItemDetails = new WorkItemDetailsPanel(idPanel, Model.of(item.getModel().getObject().getRealValue())); + workItemDetails.setOutputMarkupId(true); + add(workItemDetails); + } + + }; + return detailsPanel; + } + + + private List, String>> getWorkItemColumns(){ + List, String>> columns = new ArrayList<>(); + +// columns.add(new IconColumn>(Model.of("")) { +// +// private static final long serialVersionUID = 1L; +// +// @Override +// protected IModel createIconModel(IModel> rowModel) { +// return new IModel() { +// +// private static final long serialVersionUID = 1L; +// +// @Override +// public String getObject() { +// return WebComponentUtil.createDefaultBlackIcon(AssignmentsUtil.getTargetType(rowModel.getObject().getContainerValue().asContainerable())); +// } +// }; +// } +// +// }); + columns.add(new LinkColumn>(createStringResource("PolicyRulesPanel.nameColumn")){ + private static final long serialVersionUID = 1L; + + @Override + protected IModel createLinkModel(IModel> rowModel) { + PolyStringType workitemName = unwrapRowModel(rowModel).getName(); + return Model.of(WebComponentUtil.getTranslatedPolyString(workitemName)); + } + + @Override + public boolean isEnabled(IModel> rowModel) { + //TODO should we check any authorization? + return true; + } + + @Override + public void onClick(AjaxRequestTarget target, IModel> rowModel) { + CaseWorkItemListWithDetailsPanel.this.itemDetailsPerformed(target, rowModel); + + } + }); + + columns.addAll(ColumnUtils.getDefaultWorkItemColumns(getPageBase(), true)); + return columns; + } + + private CaseWorkItemType unwrapRowModel(IModel> rowModel){ + return rowModel.getObject().getRealValue(); + } + + private CaseWorkItemType unwrapPanelModel(){ + return getModelObject() != null && CollectionUtils.isNotEmpty(getModelObject().getValues()) ? + getModelObject().getValues().get(0).getRealValue() : null; + } + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkItemsPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkItemsPanel.java index 9f2094cca37..53b6138c5c5 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkItemsPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkItemsPanel.java @@ -11,8 +11,8 @@ import com.evolveum.midpoint.gui.api.component.ContainerableListPanel; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.gui.impl.component.icon.CompositedIconBuilder; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; import com.evolveum.midpoint.prism.PrismConstants; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.query.ObjectFilter; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkItemsTableWithDetailsPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkItemsTableWithDetailsPanel.java index 2660bc5cf34..057eb68e9ff 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkItemsTableWithDetailsPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkItemsTableWithDetailsPanel.java @@ -7,7 +7,7 @@ package com.evolveum.midpoint.web.page.admin.cases; import com.evolveum.midpoint.gui.api.component.BasePanel; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; import com.evolveum.midpoint.gui.impl.component.MultivalueContainerListPanelWithDetailsPanel; import com.evolveum.midpoint.gui.impl.session.ObjectTabStorage; import com.evolveum.midpoint.model.api.AssignmentCandidatesSpecification; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkitemsTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkitemsTabPanel.java index 3b760c1b826..ea423b8ba17 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkitemsTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/CaseWorkitemsTabPanel.java @@ -8,7 +8,7 @@ import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.web.component.form.Form; import com.evolveum.midpoint.web.component.objectdetails.AbstractObjectTabPanel; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/ChildCasesTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/ChildCasesTabPanel.java index 6567862d4a7..8ecda21847f 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/ChildCasesTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/ChildCasesTabPanel.java @@ -8,8 +8,7 @@ import com.evolveum.midpoint.gui.api.component.MainObjectListPanel; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.model.api.authentication.CompiledObjectCollectionView; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.web.component.data.column.ColumnUtils; import com.evolveum.midpoint.web.component.form.Form; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/ManualCaseTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/ManualCaseTabPanel.java index 2b877fc7563..0cebf97f73f 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/ManualCaseTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/ManualCaseTabPanel.java @@ -8,7 +8,7 @@ import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/OperationRequestCaseTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/OperationRequestCaseTabPanel.java index 8d0a4b4cbcc..d38bd6da255 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/OperationRequestCaseTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/OperationRequestCaseTabPanel.java @@ -8,7 +8,7 @@ import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; @@ -18,17 +18,12 @@ import com.evolveum.midpoint.web.component.objectdetails.AbstractObjectTabPanel; import com.evolveum.midpoint.web.component.prism.show.SceneDto; import com.evolveum.midpoint.web.component.prism.show.ScenePanel; -import com.evolveum.midpoint.web.page.admin.reports.dto.JasperReportParameterDto; -import com.evolveum.midpoint.web.page.admin.workflow.WorkItemDetailsPanel; -import com.evolveum.midpoint.wf.api.WorkflowManager; import com.evolveum.midpoint.wf.util.ChangesByState; import com.evolveum.midpoint.xml.ns._public.common.common_3.CaseType; -import org.apache.wicket.markup.html.WebMarkupContainer; + import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.model.IModel; -import org.apache.wicket.model.Model; -import org.apache.wicket.model.PropertyModel; import java.util.List; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/PageWorkItemsClaimable.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/PageWorkItemsClaimable.java index d05c264de13..8f801d87b23 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/PageWorkItemsClaimable.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/cases/PageWorkItemsClaimable.java @@ -10,8 +10,8 @@ import com.evolveum.midpoint.gui.api.GuiStyleConstants; import com.evolveum.midpoint.gui.api.component.ContainerableListPanel; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; import com.evolveum.midpoint.gui.impl.component.icon.CompositedIconBuilder; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.CaseWorkItemUtil; 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 c7f47a45897..c4f87b8b73e 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 @@ -9,9 +9,8 @@ import java.util.List; -import com.evolveum.midpoint.gui.impl.prism.ItemPanel; -import com.evolveum.midpoint.gui.impl.prism.ItemPanelSettingsBuilder; -import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.gui.impl.prism.panel.ItemHeaderPanel; +import com.evolveum.midpoint.gui.impl.prism.panel.ItemPanelSettingsBuilder; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.web.component.prism.ItemVisibility; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/AccessCertificationReviewerDto.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/AccessCertificationReviewerDto.java index f201918ddcf..ecb8eac74b8 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/AccessCertificationReviewerDto.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/certification/dto/AccessCertificationReviewerDto.java @@ -6,11 +6,10 @@ */ package com.evolveum.midpoint.web.page.admin.certification.dto; -import com.evolveum.midpoint.gui.api.page.PageBase; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.api.util.ModelServiceLocator; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismReference; import com.evolveum.midpoint.prism.PrismReferenceDefinition; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageSystemConfiguration.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageSystemConfiguration.java index f9a91f30218..49faf209e89 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageSystemConfiguration.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageSystemConfiguration.java @@ -27,7 +27,7 @@ import org.apache.wicket.model.IModel; import org.apache.wicket.request.mapper.parameter.PageParameters; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; import com.evolveum.midpoint.gui.impl.page.admin.configuration.component.GlobalPolicyRuleTabPanel; import com.evolveum.midpoint.gui.impl.page.admin.configuration.component.LoggingConfigurationTabPanel; 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 9a12929b55c..ea3fb8b94c7 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 @@ -23,9 +23,9 @@ import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.page.PageBase; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.crypto.EncryptionException; import com.evolveum.midpoint.prism.crypto.Protector; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/component/DashboardReportBasicConfigurationPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/component/DashboardReportBasicConfigurationPanel.java index 3f306c14347..4465eaa2089 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/component/DashboardReportBasicConfigurationPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/reports/component/DashboardReportBasicConfigurationPanel.java @@ -7,32 +7,17 @@ package com.evolveum.midpoint.web.page.admin.reports.component; import com.evolveum.midpoint.gui.api.component.BasePanel; -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.impl.factory.ItemRealValueModel; -import com.evolveum.midpoint.gui.impl.prism.PrismReferencePanel; -import com.evolveum.midpoint.prism.Referencable; -import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.prism.query.builder.S_FilterEntryOrEmpty; -import com.evolveum.midpoint.web.component.form.DropDownFormGroup; import com.evolveum.midpoint.web.component.form.TextAreaFormGroup; import com.evolveum.midpoint.web.component.form.TextFormGroup; import com.evolveum.midpoint.web.component.form.ValueChoosePanel; import com.evolveum.midpoint.web.page.admin.reports.dto.ReportDto; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; import com.evolveum.midpoint.xml.ns._public.common.common_3.DashboardType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ExportType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; -import org.apache.wicket.markup.html.form.ChoiceRenderer; -import org.apache.wicket.markup.html.form.EnumChoiceRenderer; -import org.apache.wicket.markup.html.form.IChoiceRenderer; import org.apache.wicket.model.IModel; import org.apache.wicket.model.PropertyModel; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/ShadowDetailsTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/ShadowDetailsTabPanel.java index c200cf3ad8f..2e336710612 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/ShadowDetailsTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/ShadowDetailsTabPanel.java @@ -10,8 +10,8 @@ import org.apache.wicket.model.IModel; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.impl.prism.ShadowPanel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.gui.impl.prism.panel.ShadowPanel; import com.evolveum.midpoint.web.component.form.Form; import com.evolveum.midpoint.web.component.objectdetails.AbstractObjectTabPanel; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/content/PageAccount.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/content/PageAccount.java index 533e5562288..510ce2a6fd8 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/content/PageAccount.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/resources/content/PageAccount.java @@ -23,12 +23,12 @@ import com.evolveum.midpoint.gui.api.component.tabs.PanelTab; import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.api.prism.ShadowWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ShadowWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.schema.GetOperationOptions; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/roles/PageRoleHistory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/roles/PageRoleHistory.java index 40e13411de9..fcb52321bcf 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/roles/PageRoleHistory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/roles/PageRoleHistory.java @@ -7,7 +7,7 @@ package com.evolveum.midpoint.web.page.admin.roles; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.security.api.AuthorizationConstants; @@ -15,11 +15,10 @@ import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.application.AuthorizationAction; import com.evolveum.midpoint.web.application.PageDescriptor; -import com.evolveum.midpoint.web.component.FocusSummaryPanel; import com.evolveum.midpoint.web.component.ObjectSummaryPanel; import com.evolveum.midpoint.web.page.admin.users.PageUserHistory; import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; + import org.apache.wicket.model.IModel; /** diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/LivesyncTokenEditorPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/LivesyncTokenEditorPanel.java index 1804747f2e2..2704ddcfa30 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/LivesyncTokenEditorPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/LivesyncTokenEditorPanel.java @@ -1,174 +1,174 @@ -/* - * Copyright (c) 2020 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.page.admin.server; - -import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.prism.delta.builder.S_ValuesEntry; -import com.evolveum.midpoint.web.page.admin.configuration.component.EmptyOnChangeAjaxFormUpdatingBehavior; - -import org.apache.wicket.Component; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.model.IModel; -import org.apache.wicket.model.StringResourceModel; - -import com.evolveum.midpoint.gui.api.component.BasePanel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismProperty; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.LoggingUtils; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.AjaxButton; -import com.evolveum.midpoint.web.component.dialog.Popupable; -import com.evolveum.midpoint.web.component.input.TextPanel; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; - -public class LivesyncTokenEditorPanel extends BasePanel> implements Popupable { - - private static final transient Trace LOGGER = TraceManager.getTrace(LivesyncTokenEditorPanel.class); - - private static final String ID_TOKEN = "token"; - private static final String ID_OK = "ok"; - private static final String ID_CANCEL = "cancel"; - - public static final ItemPath PATH_TOKEN = ItemPath.create(TaskType.F_EXTENSION, SchemaConstants.SYNC_TOKEN); - - public LivesyncTokenEditorPanel(String id, IModel> model) { - super(id, model); - } - - @Override - protected void onInitialize() { - super.onInitialize(); - initLayout(); - } - - private void initLayout() { - IModel syncTokenModel = new IModel() { - - @Override - public T getObject() { - PrismObjectWrapper taskWrapper = getModelObject(); - PrismObject task = taskWrapper.getObject(); - PrismProperty token = task.findProperty(PATH_TOKEN); - - if (token == null) { - return null; - } - - return token.getRealValue(); - } - - @Override - public void setObject(T object) { - PrismObjectWrapper taskWrapper = getModelObject(); - PrismObject task = taskWrapper.getObject(); - PrismProperty token = task.findProperty(PATH_TOKEN); - - if (token == null) { - try { - token = task.findOrCreateProperty(PATH_TOKEN); - } catch (SchemaException e) { - LoggingUtils.logUnexpectedException(LOGGER, "Cannot create token property", e); - getSession().error(getString("LivesyncTokenEditorPanel.create.token.failed", e.getMessage())); - return; - } - } - - token.setRealValue(object); - } - }; - - TextPanel tokenPanel = new TextPanel<>(ID_TOKEN, syncTokenModel); - tokenPanel.getBaseFormComponent().add(new EmptyOnChangeAjaxFormUpdatingBehavior()); - add(tokenPanel); - - AjaxButton okButton = new AjaxButton(ID_OK, createStringResource("Button.ok")) { - - @Override - public void onClick(AjaxRequestTarget ajaxRequestTarget) { - getPageBase().hideMainPopup(ajaxRequestTarget); - ObjectDelta tokenDelta = getTokenDelta(ajaxRequestTarget); - if (tokenDelta == null) { - getSession().warn(getString("LivesyncTokenEditorPanel.token.delta.empty")); - return; - } - saveTokenPerformed(tokenDelta, ajaxRequestTarget); - } - }; - add(okButton); - - AjaxButton cancelButton = new AjaxButton(ID_CANCEL, createStringResource("Button.cancel")) { - - @Override - public void onClick(AjaxRequestTarget ajaxRequestTarget) { - getPageBase().hideMainPopup(ajaxRequestTarget); - } - }; - add(cancelButton); - } - - private ObjectDelta getTokenDelta(AjaxRequestTarget target) { - TextPanel tokenPanel = (TextPanel) get(ID_TOKEN); - T newTokenValue = tokenPanel.getBaseFormComponent().getModelObject(); - try { - PrismProperty tokenProperty = getModelObject().getObject().findProperty(PATH_TOKEN); - - if (tokenProperty == null) { - tokenProperty = getModelObject().getObject().findOrCreateProperty(PATH_TOKEN); - } - - S_ValuesEntry valuesEntry = getPrismContext().deltaFor(TaskType.class).item(PATH_TOKEN, tokenProperty.getDefinition()); - if (newTokenValue == null) { - return valuesEntry.replace().asObjectDelta(getModelObject().getOid()); - } - return valuesEntry.replace(newTokenValue).asObjectDelta(getModelObject().getOid()); - } catch (SchemaException e) { - LoggingUtils.logUnexpectedException(LOGGER, "Cannot modify token", e); - getSession().error(getString("LivesyncTokenEditorPanel.modify.token.failed", e.getMessage())); - target.add(getPageBase().getFeedbackPanel()); - return null; - } - } - - protected void saveTokenPerformed(ObjectDelta tokenDelta, AjaxRequestTarget target) { - - } - - @Override - public int getWidth() { - return 400; - } - - @Override - public int getHeight() { - return 200; - } - - @Override - public String getWidthUnit() { - return "px"; - } - - @Override - public String getHeightUnit() { - return "px"; - } - - @Override - public StringResourceModel getTitle() { - return createStringResource("LivesyncTokenEditorPanel.manage.token"); - } - - @Override - public Component getComponent() { - return this; - } -} +/* + * Copyright (c) 2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.page.admin.server; + +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.delta.builder.S_ValuesEntry; +import com.evolveum.midpoint.web.page.admin.configuration.component.EmptyOnChangeAjaxFormUpdatingBehavior; + +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.StringResourceModel; + +import com.evolveum.midpoint.gui.api.component.BasePanel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismProperty; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.LoggingUtils; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.component.AjaxButton; +import com.evolveum.midpoint.web.component.dialog.Popupable; +import com.evolveum.midpoint.web.component.input.TextPanel; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; + +public class LivesyncTokenEditorPanel extends BasePanel> implements Popupable { + + private static final transient Trace LOGGER = TraceManager.getTrace(LivesyncTokenEditorPanel.class); + + private static final String ID_TOKEN = "token"; + private static final String ID_OK = "ok"; + private static final String ID_CANCEL = "cancel"; + + public static final ItemPath PATH_TOKEN = ItemPath.create(TaskType.F_EXTENSION, SchemaConstants.SYNC_TOKEN); + + public LivesyncTokenEditorPanel(String id, IModel> model) { + super(id, model); + } + + @Override + protected void onInitialize() { + super.onInitialize(); + initLayout(); + } + + private void initLayout() { + IModel syncTokenModel = new IModel() { + + @Override + public T getObject() { + PrismObjectWrapper taskWrapper = getModelObject(); + PrismObject task = taskWrapper.getObject(); + PrismProperty token = task.findProperty(PATH_TOKEN); + + if (token == null) { + return null; + } + + return token.getRealValue(); + } + + @Override + public void setObject(T object) { + PrismObjectWrapper taskWrapper = getModelObject(); + PrismObject task = taskWrapper.getObject(); + PrismProperty token = task.findProperty(PATH_TOKEN); + + if (token == null) { + try { + token = task.findOrCreateProperty(PATH_TOKEN); + } catch (SchemaException e) { + LoggingUtils.logUnexpectedException(LOGGER, "Cannot create token property", e); + getSession().error(getString("LivesyncTokenEditorPanel.create.token.failed", e.getMessage())); + return; + } + } + + token.setRealValue(object); + } + }; + + TextPanel tokenPanel = new TextPanel<>(ID_TOKEN, syncTokenModel); + tokenPanel.getBaseFormComponent().add(new EmptyOnChangeAjaxFormUpdatingBehavior()); + add(tokenPanel); + + AjaxButton okButton = new AjaxButton(ID_OK, createStringResource("Button.ok")) { + + @Override + public void onClick(AjaxRequestTarget ajaxRequestTarget) { + getPageBase().hideMainPopup(ajaxRequestTarget); + ObjectDelta tokenDelta = getTokenDelta(ajaxRequestTarget); + if (tokenDelta == null) { + getSession().warn(getString("LivesyncTokenEditorPanel.token.delta.empty")); + return; + } + saveTokenPerformed(tokenDelta, ajaxRequestTarget); + } + }; + add(okButton); + + AjaxButton cancelButton = new AjaxButton(ID_CANCEL, createStringResource("Button.cancel")) { + + @Override + public void onClick(AjaxRequestTarget ajaxRequestTarget) { + getPageBase().hideMainPopup(ajaxRequestTarget); + } + }; + add(cancelButton); + } + + private ObjectDelta getTokenDelta(AjaxRequestTarget target) { + TextPanel tokenPanel = (TextPanel) get(ID_TOKEN); + T newTokenValue = tokenPanel.getBaseFormComponent().getModelObject(); + try { + PrismProperty tokenProperty = getModelObject().getObject().findProperty(PATH_TOKEN); + + if (tokenProperty == null) { + tokenProperty = getModelObject().getObject().findOrCreateProperty(PATH_TOKEN); + } + + S_ValuesEntry valuesEntry = getPrismContext().deltaFor(TaskType.class).item(PATH_TOKEN, tokenProperty.getDefinition()); + if (newTokenValue == null) { + return valuesEntry.replace().asObjectDelta(getModelObject().getOid()); + } + return valuesEntry.replace(newTokenValue).asObjectDelta(getModelObject().getOid()); + } catch (SchemaException e) { + LoggingUtils.logUnexpectedException(LOGGER, "Cannot modify token", e); + getSession().error(getString("LivesyncTokenEditorPanel.modify.token.failed", e.getMessage())); + target.add(getPageBase().getFeedbackPanel()); + return null; + } + } + + protected void saveTokenPerformed(ObjectDelta tokenDelta, AjaxRequestTarget target) { + + } + + @Override + public int getWidth() { + return 400; + } + + @Override + public int getHeight() { + return 200; + } + + @Override + public String getWidthUnit() { + return "px"; + } + + @Override + public String getHeightUnit() { + return "px"; + } + + @Override + public StringResourceModel getTitle() { + return createStringResource("LivesyncTokenEditorPanel.manage.token"); + } + + @Override + public Component getComponent() { + return this; + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTask.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTask.java index 1608c373593..fc1c8301b5e 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTask.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTask.java @@ -3,6 +3,8 @@ import java.io.InputStream; import java.util.*; +import com.evolveum.midpoint.gui.api.prism.wrapper.*; +import com.evolveum.midpoint.gui.impl.prism.wrapper.*; import org.apache.wicket.Page; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.behavior.AttributeAppender; @@ -14,15 +16,12 @@ import org.apache.wicket.request.mapper.parameter.PageParameters; import com.evolveum.midpoint.gui.api.GuiStyleConstants; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; import com.evolveum.midpoint.gui.impl.component.AjaxCompositedIconButton; import com.evolveum.midpoint.gui.impl.component.icon.CompositedIcon; import com.evolveum.midpoint.gui.impl.component.icon.CompositedIconBuilder; import com.evolveum.midpoint.gui.impl.component.icon.IconCssStyle; -import com.evolveum.midpoint.gui.impl.prism.*; import com.evolveum.midpoint.model.api.authentication.GuiProfiledPrincipal; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismProperty; @@ -430,7 +429,7 @@ public void yesPerformed(AjaxRequestTarget target) { } private ItemDelta createDeleteItemDelta(ItemName itemName) throws SchemaException { - ItemWrapper item = getObjectWrapper().findItem(itemName, ItemWrapper.class); + ItemWrapper item = getObjectWrapper().findItem(itemName, ItemWrapper.class); if (item == null) { return null; } @@ -448,7 +447,7 @@ public void yesPerformed(AjaxRequestTarget target) { .asItemDelta(); } - + private void saveTaskChanges(AjaxRequestTarget target, ObjectDelta taskDelta){ if (taskDelta.isEmpty()) { getSession().warn("Nothing to save, no changes were made."); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskBasicTabPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskBasicTabPanel.html index f12d0a4edef..3a9995077b7 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskBasicTabPanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskBasicTabPanel.html @@ -19,8 +19,15 @@ xmlns:wicket="http://wicket.apache.org"> -
-
+
+
+
+
+
+
+
+
+ diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskBasicTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskBasicTabPanel.java index 7dd3c604d63..ec81902030d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskBasicTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskBasicTabPanel.java @@ -8,8 +8,11 @@ import java.util.*; -import com.evolveum.midpoint.prism.PrismProperty; - +import com.evolveum.midpoint.gui.api.prism.wrapper.*; +import com.evolveum.midpoint.gui.impl.prism.panel.ItemPanelSettings; +import com.evolveum.midpoint.gui.impl.prism.panel.ItemPanelSettingsBuilder; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; import com.evolveum.midpoint.web.component.prism.ValueStatus; import org.apache.commons.lang.StringUtils; @@ -20,13 +23,10 @@ import org.apache.wicket.model.IModel; import com.evolveum.midpoint.gui.api.component.BasePanel; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.api.util.WebPrismUtil; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; -import com.evolveum.midpoint.gui.impl.prism.*; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.schema.constants.ObjectTypes; @@ -140,8 +140,7 @@ public boolean isVisible() { ItemPanelSettingsBuilder builder = new ItemPanelSettingsBuilder() .visibilityHandler(visibilityHandler) .editabilityHandler(editabilityHandler) - .mandatoryHandler(getItemMandatoryHandler()) - .showOnTopLevel(true); + .mandatoryHandler(getItemMandatoryHandler()); Panel panel = getPageBase().initItemPanel(ID_MAIN_PANEL, TaskType.COMPLEX_TYPE, getModel(), builder.build()); add(panel); } catch (SchemaException e) { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskErrorsTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskErrorsTabPanel.java index b93b1b4b457..63eaf5540ff 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskErrorsTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskErrorsTabPanel.java @@ -1,156 +1,156 @@ -/* - * Copyright (c) 2010-2017 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.page.admin.server; - -import com.evolveum.midpoint.gui.api.component.BasePanel; -import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.ObjectOrdering; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.prism.query.OrderDirection; -import com.evolveum.midpoint.schema.SchemaConstantsGenerated; -import com.evolveum.midpoint.web.component.data.BoxedTablePanel; -import com.evolveum.midpoint.web.component.data.SelectableBeanObjectDataProvider; -import com.evolveum.midpoint.web.component.util.SelectableBean; -import com.evolveum.midpoint.web.page.admin.server.dto.TaskErrorSelectableBeanImpl; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationExecutionType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultStatusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; -import org.apache.wicket.Component; -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.extensions.markup.html.repeater.data.table.PropertyColumn; -import org.apache.wicket.extensions.markup.html.repeater.util.SortParam; -import org.apache.wicket.markup.html.basic.Label; -import org.apache.wicket.markup.repeater.Item; -import org.apache.wicket.model.IModel; -import org.jetbrains.annotations.NotNull; - -import javax.xml.namespace.QName; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * Created by honchar. - */ -public class TaskErrorsTabPanel extends BasePanel> implements RefreshableTabPanel { - private static final long serialVersionUID = 1L; - - private static final String ID_TASK_ERRORS = "taskErrors"; - - public TaskErrorsTabPanel(String id, LoadableModel> taskWrapperModel) { - super(id, taskWrapperModel); - - } - - @Override - protected void onInitialize() { - super.onInitialize(); - initLayout(); - setOutputMarkupId(true); - } - - private void initLayout() { - - - SelectableBeanObjectDataProvider provider = new SelectableBeanObjectDataProvider(this, ObjectType.class, null) { - - @Override - public SelectableBean createDataObjectWrapper(ObjectType obj) { - return new TaskErrorSelectableBeanImpl<>(obj, getModelObject().getOid()); - } - - @Override - public ObjectQuery getQuery() { - return createContentQuery(getModelObject().getOid(), getPageBase()); - } - - @NotNull - @Override - protected List createObjectOrderings(SortParam sortParam) { - if (sortParam != null && sortParam.getProperty() != null) { - OrderDirection order = sortParam.isAscending() ? OrderDirection.ASCENDING : OrderDirection.DESCENDING; - ItemPath ordering; - if (sortParam.getProperty().equals(TaskErrorSelectableBeanImpl.F_ERROR_TIMESTAMP)) { - ordering = ItemPath.create("operationExecution", "timestamp"); - } else { - ordering = ItemPath.create(new QName(SchemaConstantsGenerated.NS_COMMON, sortParam.getProperty())); - } - return Collections.singletonList( - getPrismContext().queryFactory().createOrdering( - ordering, order)); - } else { - return Collections.emptyList(); - } - } - }; - - BoxedTablePanel> table = new BoxedTablePanel<>(ID_TASK_ERRORS, provider, initColumns()); - table.setOutputMarkupId(true); - add(table); - - } - - private List, String>> initColumns() { - List, String>> columns = new ArrayList<>(); - columns.add(new PropertyColumn, String>(createStringResource("pageTaskEdit.taskErros.objectName"), TaskErrorSelectableBeanImpl.F_OBJECT_REF_NAME){ - @Override - public String getSortProperty() { - return "name"; - } - }); - columns.add(new PropertyColumn<>(createStringResource("pageTaskEdit.taskErros.status"), TaskErrorSelectableBeanImpl.F_STATUS)); - columns.add(new AbstractColumn, String>(createStringResource("pageTaskEdit.taskErros.timestamp"), TaskErrorSelectableBeanImpl.F_ERROR_TIMESTAMP){ - private static final long serialVersionUID = 1L; - - @Override - public void populateItem(Item>> cellItem, String componentId, - IModel> rowModel) { - Label label = new Label(componentId, (IModel) () -> WebComponentUtil.getShortDateTimeFormattedValue(rowModel.getObject().getErrorTimestamp(), getPageBase())); - cellItem.add(label); - } - - }); - columns.add(new PropertyColumn<>(createStringResource("pageTaskEdit.taskErros.message"), TaskErrorSelectableBeanImpl.F_MESSAGE)); - return columns; - } - - private ObjectQuery createContentQuery(String taskOid, PageBase pageBase){ - return pageBase.getPrismContext().queryFor(ObjectType.class) - .exists(ObjectType.F_OPERATION_EXECUTION) - .block() - .item(OperationExecutionType.F_TASK_REF).ref(taskOid) - .and() - .block().item(OperationExecutionType.F_STATUS) - .eq(OperationResultStatusType.FATAL_ERROR) - .or().item(OperationExecutionType.F_STATUS) - .eq(OperationResultStatusType.PARTIAL_ERROR) - .or().item(OperationExecutionType.F_STATUS) - .eq(OperationResultStatusType.WARNING) - .endBlock() - .endBlock() - .build(); - } - - @Override - public Collection getComponentsToUpdate() { - return Collections.singleton(get(ID_TASK_ERRORS)); - } - - @Override - protected void detachModel() { - super.detachModel(); - ((LoadableModel) getModel()).reset(); - } -} +/* + * Copyright (c) 2010-2017 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.page.admin.server; + +import com.evolveum.midpoint.gui.api.component.BasePanel; +import com.evolveum.midpoint.gui.api.model.LoadableModel; +import com.evolveum.midpoint.gui.api.page.PageBase; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.ObjectOrdering; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.OrderDirection; +import com.evolveum.midpoint.schema.SchemaConstantsGenerated; +import com.evolveum.midpoint.web.component.data.BoxedTablePanel; +import com.evolveum.midpoint.web.component.data.SelectableBeanObjectDataProvider; +import com.evolveum.midpoint.web.component.util.SelectableBean; +import com.evolveum.midpoint.web.page.admin.server.dto.TaskErrorSelectableBeanImpl; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationExecutionType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultStatusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; +import org.apache.wicket.Component; +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.extensions.markup.html.repeater.data.table.PropertyColumn; +import org.apache.wicket.extensions.markup.html.repeater.util.SortParam; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.repeater.Item; +import org.apache.wicket.model.IModel; +import org.jetbrains.annotations.NotNull; + +import javax.xml.namespace.QName; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * Created by honchar. + */ +public class TaskErrorsTabPanel extends BasePanel> implements RefreshableTabPanel { + private static final long serialVersionUID = 1L; + + private static final String ID_TASK_ERRORS = "taskErrors"; + + public TaskErrorsTabPanel(String id, LoadableModel> taskWrapperModel) { + super(id, taskWrapperModel); + + } + + @Override + protected void onInitialize() { + super.onInitialize(); + initLayout(); + setOutputMarkupId(true); + } + + private void initLayout() { + + + SelectableBeanObjectDataProvider provider = new SelectableBeanObjectDataProvider(this, ObjectType.class, null) { + + @Override + public SelectableBean createDataObjectWrapper(ObjectType obj) { + return new TaskErrorSelectableBeanImpl<>(obj, getModelObject().getOid()); + } + + @Override + public ObjectQuery getQuery() { + return createContentQuery(getModelObject().getOid(), getPageBase()); + } + + @NotNull + @Override + protected List createObjectOrderings(SortParam sortParam) { + if (sortParam != null && sortParam.getProperty() != null) { + OrderDirection order = sortParam.isAscending() ? OrderDirection.ASCENDING : OrderDirection.DESCENDING; + ItemPath ordering; + if (sortParam.getProperty().equals(TaskErrorSelectableBeanImpl.F_ERROR_TIMESTAMP)) { + ordering = ItemPath.create("operationExecution", "timestamp"); + } else { + ordering = ItemPath.create(new QName(SchemaConstantsGenerated.NS_COMMON, sortParam.getProperty())); + } + return Collections.singletonList( + getPrismContext().queryFactory().createOrdering( + ordering, order)); + } else { + return Collections.emptyList(); + } + } + }; + + BoxedTablePanel> table = new BoxedTablePanel<>(ID_TASK_ERRORS, provider, initColumns()); + table.setOutputMarkupId(true); + add(table); + + } + + private List, String>> initColumns() { + List, String>> columns = new ArrayList<>(); + columns.add(new PropertyColumn, String>(createStringResource("pageTaskEdit.taskErros.objectName"), TaskErrorSelectableBeanImpl.F_OBJECT_REF_NAME){ + @Override + public String getSortProperty() { + return "name"; + } + }); + columns.add(new PropertyColumn<>(createStringResource("pageTaskEdit.taskErros.status"), TaskErrorSelectableBeanImpl.F_STATUS)); + columns.add(new AbstractColumn, String>(createStringResource("pageTaskEdit.taskErros.timestamp"), TaskErrorSelectableBeanImpl.F_ERROR_TIMESTAMP){ + private static final long serialVersionUID = 1L; + + @Override + public void populateItem(Item>> cellItem, String componentId, + IModel> rowModel) { + Label label = new Label(componentId, (IModel) () -> WebComponentUtil.getShortDateTimeFormattedValue(rowModel.getObject().getErrorTimestamp(), getPageBase())); + cellItem.add(label); + } + + }); + columns.add(new PropertyColumn<>(createStringResource("pageTaskEdit.taskErros.message"), TaskErrorSelectableBeanImpl.F_MESSAGE)); + return columns; + } + + private ObjectQuery createContentQuery(String taskOid, PageBase pageBase){ + return pageBase.getPrismContext().queryFor(ObjectType.class) + .exists(ObjectType.F_OPERATION_EXECUTION) + .block() + .item(OperationExecutionType.F_TASK_REF).ref(taskOid) + .and() + .block().item(OperationExecutionType.F_STATUS) + .eq(OperationResultStatusType.FATAL_ERROR) + .or().item(OperationExecutionType.F_STATUS) + .eq(OperationResultStatusType.PARTIAL_ERROR) + .or().item(OperationExecutionType.F_STATUS) + .eq(OperationResultStatusType.WARNING) + .endBlock() + .endBlock() + .build(); + } + + @Override + public Collection getComponentsToUpdate() { + return Collections.singleton(get(ID_TASK_ERRORS)); + } + + @Override + protected void detachModel() { + super.detachModel(); + ((LoadableModel) getModel()).reset(); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskHandlerSelectorPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskHandlerSelectorPanel.html index f32bc4d9712..239b3642501 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskHandlerSelectorPanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskHandlerSelectorPanel.html @@ -1,4 +1,4 @@ - - -
- -
-
-
-
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskHandlerSelectorPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskHandlerSelectorPanel.java index 5c24326e511..95e70ee2bb0 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskHandlerSelectorPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskHandlerSelectorPanel.java @@ -6,16 +6,17 @@ */ package com.evolveum.midpoint.web.page.admin.server; +import com.evolveum.midpoint.gui.impl.prism.panel.ItemPanelSettings; +import com.evolveum.midpoint.gui.impl.prism.panel.PrismPropertyPanel; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismPropertyValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; import org.apache.wicket.ajax.form.OnChangeAjaxBehavior; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.model.IModel; -import com.evolveum.midpoint.gui.api.factory.GuiComponentFactory; -import com.evolveum.midpoint.gui.impl.prism.*; import com.evolveum.midpoint.web.component.prism.InputPanel; public class TaskHandlerSelectorPanel extends PrismPropertyPanel { @@ -36,10 +37,10 @@ public TaskHandlerSelectorPanel(String id, IModel> } @Override - protected Component createValuePanel(ListItem> item, GuiComponentFactory factory, ItemVisibilityHandler visibilityHandler, ItemEditabilityHandler editabilityHandler) { - Component handlerPanel = super.createValuePanel(item, factory, visibilityHandler, editabilityHandler); - if (handlerPanel.get("form:input") instanceof InputPanel) { - ((InputPanel) handlerPanel.get("form:input")).getBaseFormComponent().add(new OnChangeAjaxBehavior() { + protected Component createValuePanel(ListItem> item) { + Component handlerPanel = super.createValuePanel(item); + if (handlerPanel.get("valueForm:valueContainer:input") instanceof InputPanel) { + ((InputPanel) handlerPanel.get("valueForm:valueContainer:input")).getBaseFormComponent().add(new OnChangeAjaxBehavior() { @Override protected void onUpdate(AjaxRequestTarget ajaxRequestTarget) { diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskInternalPerformanceTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskInternalPerformanceTabPanel.java index 00989286192..7ca3d8c8a0f 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskInternalPerformanceTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskInternalPerformanceTabPanel.java @@ -1,165 +1,165 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.page.admin.server; - -import com.evolveum.midpoint.gui.api.component.BasePanel; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.schema.statistics.*; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.LoggingUtils; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.AceEditor; -import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationStatsType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkBucketManagementPerformanceInformationType; -import org.apache.wicket.Component; -import org.apache.wicket.model.IModel; - -import java.util.Collection; -import java.util.Collections; - -/** - * - */ -public class TaskInternalPerformanceTabPanel extends BasePanel> implements RefreshableTabPanel { - private static final long serialVersionUID = 1L; - - private static final transient Trace LOGGER = TraceManager.getTrace(TaskInternalPerformanceTabPanel.class); - - private static final String ID_INFORMATION = "information"; - - - //private static final Trace LOGGER = TraceManager.getTrace(TaskInternalPerformanceTabPanel.class); - - public TaskInternalPerformanceTabPanel(String id, IModel> statsModel) { - super(id, statsModel); - } - - @Override - protected void onInitialize() { - super.onInitialize(); - initLayout(); - setOutputMarkupId(true); - } - - private void initLayout() { - AceEditor informationText = new AceEditor(ID_INFORMATION, createStringModel()) { - @Override - public int getHeight() { - return 300; - } - - @Override - public boolean isResizeToMaxHeight() { - return true; - } - }; - informationText.setReadonly(true); -// informationText.setHeight(300); -// informationText.setResizeToMaxHeight(true); - informationText.setMode(null); - add(informationText); - - } - - private IModel createStringModel() { - return new IModel() { - @Override - public String getObject() { - return getStatistics(); - } - - @Override - public void setObject(String object) { - // nothing to do here - } - }; - } - - @SuppressWarnings("Duplicates") - private String getStatistics() { - PrismContainerWrapper statsContainer = getModelObject(); - if (statsContainer == null) { - return "No operation statistics available"; - } - - OperationStatsType statistics; - try { - PrismContainerValueWrapper statsValue = statsContainer.getValue(); - statistics = statsValue.getRealValue(); - } catch (SchemaException e) { - LoggingUtils.logUnexpectedException(LOGGER, "Cannot get statistics from task", e); - return "No operation statistics available"; - } - - if (statistics == null) { - return "No operation statistics available"; - } - StringBuilder sb = new StringBuilder(); - if (statistics.getRepositoryPerformanceInformation() != null) { - sb.append("Repository performance information:\n") - .append(RepositoryPerformanceInformationUtil.format(statistics.getRepositoryPerformanceInformation())) - .append("\n"); - } - WorkBucketManagementPerformanceInformationType buckets = statistics.getWorkBucketManagementPerformanceInformation(); - if (buckets != null && !buckets.getOperation().isEmpty()) { - sb.append("Work buckets management performance information:\n") - .append(TaskWorkBucketManagementPerformanceInformationUtil.format(buckets)) - .append("\n"); - } - if (statistics.getCachesPerformanceInformation() != null) { - sb.append("Cache performance information:\n") - .append(CachePerformanceInformationUtil.format(statistics.getCachesPerformanceInformation())) - .append("\n"); - } - if (statistics.getOperationsPerformanceInformation() != null) { - sb.append("Methods performance information:\n") - .append(OperationsPerformanceInformationUtil.format(statistics.getOperationsPerformanceInformation())) - .append("\n"); - } - sb.append("\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------\n"); - sb.append("Other performance-related information that is shown elsewhere (provided here just for completeness):\n\n"); - if (statistics.getIterativeTaskInformation() != null) { - sb.append("Iterative task information:\n") - .append(IterativeTaskInformation.format(statistics.getIterativeTaskInformation())) - .append("\n"); - } - if (statistics.getActionsExecutedInformation() != null) { - sb.append("Actions executed:\n") - .append(ActionsExecutedInformation.format(statistics.getActionsExecutedInformation())) - .append("\n"); - } -// if (statistics.getSynchronizationInformation() != null) { -// sb.append("Synchronization information:\n") -// .append(SynchronizationInformation.format(statistics.getSynchronizationInformation())) -// .append("\n"); -// } - if (statistics.getEnvironmentalPerformanceInformation() != null) { - sb.append("Environmental performance information:\n") - .append(EnvironmentalPerformanceInformation.format(statistics.getEnvironmentalPerformanceInformation())) - .append("\n"); - } - if (statistics.getCachingConfiguration() != null) { - sb.append("\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------\n"); - sb.append("Caching configuration:\n\n"); - sb.append(statistics.getCachingConfiguration()); - } - return sb.toString(); - } - - - @Override - public Collection getComponentsToUpdate() { - return Collections.singleton(this); - } - - @Override - protected void detachModel() { - super.detachModel(); - } -} +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.page.admin.server; + +import com.evolveum.midpoint.gui.api.component.BasePanel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.schema.statistics.*; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.LoggingUtils; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.component.AceEditor; +import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationStatsType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkBucketManagementPerformanceInformationType; +import org.apache.wicket.Component; +import org.apache.wicket.model.IModel; + +import java.util.Collection; +import java.util.Collections; + +/** + * + */ +public class TaskInternalPerformanceTabPanel extends BasePanel> implements RefreshableTabPanel { + private static final long serialVersionUID = 1L; + + private static final transient Trace LOGGER = TraceManager.getTrace(TaskInternalPerformanceTabPanel.class); + + private static final String ID_INFORMATION = "information"; + + + //private static final Trace LOGGER = TraceManager.getTrace(TaskInternalPerformanceTabPanel.class); + + public TaskInternalPerformanceTabPanel(String id, IModel> statsModel) { + super(id, statsModel); + } + + @Override + protected void onInitialize() { + super.onInitialize(); + initLayout(); + setOutputMarkupId(true); + } + + private void initLayout() { + AceEditor informationText = new AceEditor(ID_INFORMATION, createStringModel()) { + @Override + public int getHeight() { + return 300; + } + + @Override + public boolean isResizeToMaxHeight() { + return true; + } + }; + informationText.setReadonly(true); +// informationText.setHeight(300); +// informationText.setResizeToMaxHeight(true); + informationText.setMode(null); + add(informationText); + + } + + private IModel createStringModel() { + return new IModel() { + @Override + public String getObject() { + return getStatistics(); + } + + @Override + public void setObject(String object) { + // nothing to do here + } + }; + } + + @SuppressWarnings("Duplicates") + private String getStatistics() { + PrismContainerWrapper statsContainer = getModelObject(); + if (statsContainer == null) { + return "No operation statistics available"; + } + + OperationStatsType statistics; + try { + PrismContainerValueWrapper statsValue = statsContainer.getValue(); + statistics = statsValue.getRealValue(); + } catch (SchemaException e) { + LoggingUtils.logUnexpectedException(LOGGER, "Cannot get statistics from task", e); + return "No operation statistics available"; + } + + if (statistics == null) { + return "No operation statistics available"; + } + StringBuilder sb = new StringBuilder(); + if (statistics.getRepositoryPerformanceInformation() != null) { + sb.append("Repository performance information:\n") + .append(RepositoryPerformanceInformationUtil.format(statistics.getRepositoryPerformanceInformation())) + .append("\n"); + } + WorkBucketManagementPerformanceInformationType buckets = statistics.getWorkBucketManagementPerformanceInformation(); + if (buckets != null && !buckets.getOperation().isEmpty()) { + sb.append("Work buckets management performance information:\n") + .append(TaskWorkBucketManagementPerformanceInformationUtil.format(buckets)) + .append("\n"); + } + if (statistics.getCachesPerformanceInformation() != null) { + sb.append("Cache performance information:\n") + .append(CachePerformanceInformationUtil.format(statistics.getCachesPerformanceInformation())) + .append("\n"); + } + if (statistics.getOperationsPerformanceInformation() != null) { + sb.append("Methods performance information:\n") + .append(OperationsPerformanceInformationUtil.format(statistics.getOperationsPerformanceInformation())) + .append("\n"); + } + sb.append("\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------\n"); + sb.append("Other performance-related information that is shown elsewhere (provided here just for completeness):\n\n"); + if (statistics.getIterativeTaskInformation() != null) { + sb.append("Iterative task information:\n") + .append(IterativeTaskInformation.format(statistics.getIterativeTaskInformation())) + .append("\n"); + } + if (statistics.getActionsExecutedInformation() != null) { + sb.append("Actions executed:\n") + .append(ActionsExecutedInformation.format(statistics.getActionsExecutedInformation())) + .append("\n"); + } +// if (statistics.getSynchronizationInformation() != null) { +// sb.append("Synchronization information:\n") +// .append(SynchronizationInformation.format(statistics.getSynchronizationInformation())) +// .append("\n"); +// } + if (statistics.getEnvironmentalPerformanceInformation() != null) { + sb.append("Environmental performance information:\n") + .append(EnvironmentalPerformanceInformation.format(statistics.getEnvironmentalPerformanceInformation())) + .append("\n"); + } + if (statistics.getCachingConfiguration() != null) { + sb.append("\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------\n"); + sb.append("Caching configuration:\n\n"); + sb.append(statistics.getCachingConfiguration()); + } + return sb.toString(); + } + + + @Override + public Collection getComponentsToUpdate() { + return Collections.singleton(this); + } + + @Override + protected void detachModel() { + super.detachModel(); + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskMainPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskMainPanel.java index d048173f994..c518d0044e5 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskMainPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskMainPanel.java @@ -10,6 +10,12 @@ import java.util.List; import javax.xml.namespace.QName; +import com.evolveum.midpoint.gui.impl.prism.panel.ItemHeaderPanel; + +import com.evolveum.midpoint.gui.impl.prism.panel.ItemPanelSettingsBuilder; + +import com.evolveum.midpoint.gui.impl.prism.panel.SingleContainerPanel; + import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.extensions.markup.html.tabs.ITab; import org.apache.wicket.markup.html.WebMarkupContainer; @@ -21,13 +27,12 @@ import com.evolveum.midpoint.gui.api.component.tabs.PanelTab; import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.ObjectTabVisibleBehavior; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.impl.prism.ItemEditabilityHandler; -import com.evolveum.midpoint.gui.impl.prism.ItemPanelSettingsBuilder; -import com.evolveum.midpoint.gui.impl.prism.ItemVisibilityHandler; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemEditabilityHandler; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemVisibilityHandler; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.util.exception.SchemaException; @@ -126,8 +131,14 @@ public boolean isVisible(){ @Override public WebMarkupContainer createPanel(String panelId) { - ItemVisibilityHandler visibilityHandler = wrapper -> ItemVisibility.AUTO; - return createContainerPanel(panelId, ScheduleType.COMPLEX_TYPE, PrismContainerWrapperModel.fromContainerWrapper(getObjectModel(), TaskType.F_SCHEDULE), visibilityHandler, getTaskEditabilityHandler()); + return new SingleContainerPanel(panelId, PrismContainerWrapperModel.fromContainerWrapper(getObjectModel(), TaskType.F_SCHEDULE), ScheduleType.COMPLEX_TYPE) { + + @Override + protected ItemEditabilityHandler getEditabilityHandler() { + return TaskMainPanel.this.getTaskEditabilityHandler(); + } + }; + } }); } @@ -148,9 +159,18 @@ public boolean isVisible(){ @Override public WebMarkupContainer createPanel(String panelId) { - ItemVisibilityHandler visibilityHandler = wrapper -> getWorkManagementVisibility(wrapper.getPath()); - return createContainerPanel(panelId, TaskType.COMPLEX_TYPE, - PrismContainerWrapperModel.fromContainerWrapper(getObjectModel(), TaskType.F_WORK_MANAGEMENT), visibilityHandler, getTaskEditabilityHandler()); + return new SingleContainerPanel(panelId, PrismContainerWrapperModel.fromContainerWrapper(getObjectModel(), TaskType.F_WORK_MANAGEMENT), TaskWorkManagementType.COMPLEX_TYPE) { + + @Override + protected ItemVisibility getVisibity(ItemPath itemPath) { + return getWorkManagementVisibility(itemPath); + } + + @Override + protected ItemEditabilityHandler getEditabilityHandler() { + return getTaskEditabilityHandler(); + } + }; } }); } @@ -391,22 +411,6 @@ public boolean isEnabled() { getMainForm().add(saveButton); } - - private Panel createContainerPanel(String id, QName typeName, IModel> model, ItemVisibilityHandler visibilityHandler, ItemEditabilityHandler editabilityHandler) { - try { - ItemPanelSettingsBuilder builder = new ItemPanelSettingsBuilder() - .visibilityHandler(visibilityHandler) - .editabilityHandler(editabilityHandler) - .showOnTopLevel(true); - return getDetailsPage().initItemPanel(id, typeName, model, builder.build()); - } catch (SchemaException e) { - LOGGER.error("Cannot create panel for {}, {}", typeName, e.getMessage(), e); - getSession().error("Cannot create panel for " + typeName); // TODO opertion result? localization? - } - - return null; - } - private ItemEditabilityHandler getTaskEditabilityHandler(){ return wrapper -> !WebComponentUtil.isRunningTask(getTask()); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskOperationStatisticsPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskOperationStatisticsPanel.java index 32f849570f0..151ae2748dc 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskOperationStatisticsPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskOperationStatisticsPanel.java @@ -1,254 +1,254 @@ -package com.evolveum.midpoint.web.page.admin.server; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import javax.xml.datatype.XMLGregorianCalendar; - -import org.apache.wicket.Component; -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.extensions.markup.html.repeater.data.table.PropertyColumn; -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.PropertyModel; - -import com.evolveum.midpoint.gui.api.component.BasePanel; -import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.schema.constants.ObjectTypes; -import com.evolveum.midpoint.schema.util.TaskTypeUtil; -import com.evolveum.midpoint.task.api.TaskCategory; -import com.evolveum.midpoint.web.component.data.BoxedTablePanel; -import com.evolveum.midpoint.web.component.data.column.EnumPropertyColumn; -import com.evolveum.midpoint.web.component.util.ListDataProvider; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; - -public class TaskOperationStatisticsPanel extends BasePanel> implements RefreshableTabPanel { - - private static final String ID_PROCESSING_INFO = "processingInfo"; - private static final String ID_SYNCHORNIZATION_SITUATIONS = "synchronizationSituation"; - private static final String ID_ACTION_ENTRY = "actionEntry"; - private static final String ID_RESULTING_ENTRY = "resultingEntry"; - - private static final Collection WALL_CLOCK_AVG_CATEGORIES = Arrays.asList( - TaskCategory.BULK_ACTIONS, TaskCategory.IMPORTING_ACCOUNTS, TaskCategory.RECOMPUTATION, TaskCategory.RECONCILIATION, - TaskCategory.UTIL // this is a megahack: only utility tasks that count objects are DeleteTask and ShadowIntegrityCheck - ); - - private LoadableModel statisticsModel; - - public TaskOperationStatisticsPanel(String id, IModel> model) { - super(id, model); - - statisticsModel = createOperationStatsModel(); - } - - private LoadableModel createOperationStatsModel() { - - return new LoadableModel(true) { - - @Override - protected OperationStatsType load() { - PrismObject task = getModelObject().getObject(); - return TaskTypeUtil.getAggregatedOperationStats(task.asObjectable(), getPrismContext()); - } - }; - } - - @Override - protected void onInitialize() { - super.onInitialize(); - - initLayout(); - setOutputMarkupId(true); - } - - private void initLayout() { - - TaskIterativeInformationPanel infoPanel = new TaskIterativeInformationPanel(ID_PROCESSING_INFO, new PropertyModel<>(statisticsModel, OperationStatsType.F_ITERATIVE_TASK_INFORMATION.getLocalPart())) { - - - @Override - protected Long getWallClockAverage(int objectsTotal) { - if (objectsTotal == 0) { - return null; - } - - TaskType task = TaskOperationStatisticsPanel.this.getModelObject().getObject().asObjectable(); - if (!WALL_CLOCK_AVG_CATEGORIES.contains(task.getCategory())) { - return null; - } - - Long started = WebComponentUtil.xgc2long(task.getLastRunStartTimestamp()); - if (started == null) { - return null; - } - Long finished = WebComponentUtil.xgc2long(task.getLastRunFinishTimestamp()); - if (finished == null || finished < started) { - finished = System.currentTimeMillis(); - } - - return (finished - started) / objectsTotal; - } - }; - infoPanel.setOutputMarkupId(true); - add(infoPanel); - - - PropertyModel> syncInfoModel = new PropertyModel>(statisticsModel, "") { - - @Override - public List getObject() { - OperationStatsType statsType = statisticsModel.getObject(); - if (statsType == null) { - return null; - } - - SynchronizationInformationType syncInfo = statsType.getSynchronizationInformation(); - if(syncInfo == null) { - return null; - } - - List infos = new ArrayList<>(); - infos.add(new SynchronizationInformationDto("Unmatched",syncInfo.getCountUnmatched(), syncInfo.getCountUnmatchedAfter())); - infos.add(new SynchronizationInformationDto("Unlinked",syncInfo.getCountUnlinked(), syncInfo.getCountUnlinkedAfter())); - infos.add(new SynchronizationInformationDto("Linked",syncInfo.getCountLinked(), syncInfo.getCountLinkedAfter())); - infos.add(new SynchronizationInformationDto("Deleted",syncInfo.getCountDeleted(), syncInfo.getCountDeletedAfter())); - infos.add(new SynchronizationInformationDto("Disputed",syncInfo.getCountDisputed(), syncInfo.getCountDisputedAfter())); - infos.add(new SynchronizationInformationDto("Protected",syncInfo.getCountProtected(), syncInfo.getCountProtectedAfter())); - infos.add(new SynchronizationInformationDto("No sync policy",syncInfo.getCountNoSynchronizationPolicy(), syncInfo.getCountNoSynchronizationPolicyAfter())); - infos.add(new SynchronizationInformationDto("Sync disabled",syncInfo.getCountSynchronizationDisabled(), syncInfo.getCountSynchronizationDisabledAfter())); - infos.add(new SynchronizationInformationDto("Not applicable for task",syncInfo.getCountNotApplicableForTask(), syncInfo.getCountNotApplicableForTaskAfter())); - - return infos; - } - }; - - ListDataProvider syncDataProvider = new ListDataProvider(this, syncInfoModel) { - @Override - public boolean isUseCache() { - return false; - } - }; - - List> syncColumns = new ArrayList<>(); - syncColumns.add(new PropertyColumn<>(createStringResource("TaskOperationStatisticsPanel.situation"), SynchronizationInformationDto.F_ACTION_NAME)); - syncColumns.add(new PropertyColumn<>(createStringResource("TaskOperationStatisticsPanel.countBefore"), SynchronizationInformationDto.F_COUNT_BEFORE)); - syncColumns.add(new PropertyColumn<>(createStringResource("TaskOperationStatisticsPanel.countAfter"), SynchronizationInformationDto.F_COUNT_AFTER)); - - BoxedTablePanel table = new BoxedTablePanel(ID_SYNCHORNIZATION_SITUATIONS, syncDataProvider, syncColumns) { - @Override - protected boolean hideFooterIfSinglePage() { - return true; - } - }; - - table.setOutputMarkupId(true); - add(table); - - ListDataProvider objectActionsEntry = createActionsEntryProvider(OperationStatsType.F_ACTIONS_EXECUTED_INFORMATION.getLocalPart() + "." + ActionsExecutedInformationType.F_RESULTING_OBJECT_ACTIONS_ENTRY); - BoxedTablePanel actionTable = new BoxedTablePanel(ID_ACTION_ENTRY, objectActionsEntry, createActionEntryColumns()) { - @Override - protected boolean hideFooterIfSinglePage() { - return true; - } - }; - - actionTable.setOutputMarkupId(true); - add(actionTable); - - - BoxedTablePanel resultingEntry = new BoxedTablePanel(ID_RESULTING_ENTRY, createActionsEntryProvider(OperationStatsType.F_ACTIONS_EXECUTED_INFORMATION.getLocalPart() + "." + ActionsExecutedInformationType.F_OBJECT_ACTIONS_ENTRY), createActionEntryColumns()) { - @Override - protected boolean hideFooterIfSinglePage() { - return true; - } - }; - - resultingEntry.setOutputMarkupId(true); - add(resultingEntry); - - } - - private ListDataProvider createActionsEntryProvider(String expression) { - return new ListDataProvider<>(this, - new PropertyModel<>(statisticsModel, expression)); - } - - private List> createActionEntryColumns() { - List> resultingEntryColumns = new ArrayList<>(); - resultingEntryColumns.add(new AbstractColumn(createStringResource("ObjectActionsExecutedEntryType.objectType")) { - @Override - public void populateItem(Item> item, String id, IModel iModel) { - ObjectActionsExecutedEntryType entry = iModel.getObject(); - ObjectTypes objectType = null; - if (entry != null) { - if (entry.getObjectType() != null) { - objectType = ObjectTypes.getObjectTypeFromTypeQName(entry.getObjectType()); - } - } - item.add(new Label(id, createStringResource(objectType))); - } - }); - resultingEntryColumns.add(new EnumPropertyColumn<>(createStringResource("ObjectActionsExecutedEntryType.operation"), ObjectActionsExecutedEntryType.F_OPERATION.getLocalPart())); - resultingEntryColumns.add(new AbstractColumn(createStringResource("ObjectActionsExecutedEntryType.chanel")) { - @Override - public void populateItem(Item> item, String id, IModel iModel) { - String channel = iModel.getObject().getChannel(); - String key = ""; - if (channel != null && !channel.isEmpty()) { - key = "Channel." + WebComponentUtil.getSimpleChannel(channel); - } - item.add(new Label(id, createStringResource(key))); - } - }); - resultingEntryColumns.add(new PropertyColumn<>(createStringResource("ObjectActionsExecutedEntryType.totalSuccessCount"), ObjectActionsExecutedEntryType.F_TOTAL_SUCCESS_COUNT.getLocalPart())); - resultingEntryColumns.add(new PropertyColumn<>(createStringResource("ObjectActionsExecutedEntryType.lastSuccessDisplayName"), ObjectActionsExecutedEntryType.F_LAST_SUCCESS_OBJECT_DISPLAY_NAME.getLocalPart())); - resultingEntryColumns.add(new AbstractColumn(createStringResource("ObjectActionsExecutedEntryType.lastSuccessTimestamp")) { - @Override - public void populateItem(Item> item, String id, IModel iModel) { - XMLGregorianCalendar timestamp = iModel.getObject().getLastSuccessTimestamp(); - item.add(new Label(id, WebComponentUtil.formatDate(timestamp))); - } - }); - resultingEntryColumns.add(new PropertyColumn<>(createStringResource("ObjectActionsExecutedEntryType.totalFailureCount"), ObjectActionsExecutedEntryType.F_TOTAL_FAILURE_COUNT.getLocalPart())); - return resultingEntryColumns; - } - - @Override - public Collection getComponentsToUpdate() { - statisticsModel.reset(); - List components = new ArrayList<>(); - components.add(get(ID_ACTION_ENTRY)); - components.add(get(ID_PROCESSING_INFO)); - components.add(get(ID_RESULTING_ENTRY)); - components.add(get(ID_SYNCHORNIZATION_SITUATIONS)); - return components; - } - - class SynchronizationInformationDto implements Serializable { - - public static final String F_ACTION_NAME = "actionName"; - public static final String F_COUNT_BEFORE = "countBefore"; - public static final String F_COUNT_AFTER = "countAfter"; - - private String actionName; - private int countBefore; - private int countAfter; - - public SynchronizationInformationDto(String actionName, int countBefore, int countAfter) { - this.actionName = actionName; - this.countBefore = countBefore; - this.countAfter = countAfter; - } - - } - -} +package com.evolveum.midpoint.web.page.admin.server; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.apache.wicket.Component; +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.extensions.markup.html.repeater.data.table.PropertyColumn; +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.PropertyModel; + +import com.evolveum.midpoint.gui.api.component.BasePanel; +import com.evolveum.midpoint.gui.api.model.LoadableModel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.schema.constants.ObjectTypes; +import com.evolveum.midpoint.schema.util.TaskTypeUtil; +import com.evolveum.midpoint.task.api.TaskCategory; +import com.evolveum.midpoint.web.component.data.BoxedTablePanel; +import com.evolveum.midpoint.web.component.data.column.EnumPropertyColumn; +import com.evolveum.midpoint.web.component.util.ListDataProvider; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; + +public class TaskOperationStatisticsPanel extends BasePanel> implements RefreshableTabPanel { + + private static final String ID_PROCESSING_INFO = "processingInfo"; + private static final String ID_SYNCHORNIZATION_SITUATIONS = "synchronizationSituation"; + private static final String ID_ACTION_ENTRY = "actionEntry"; + private static final String ID_RESULTING_ENTRY = "resultingEntry"; + + private static final Collection WALL_CLOCK_AVG_CATEGORIES = Arrays.asList( + TaskCategory.BULK_ACTIONS, TaskCategory.IMPORTING_ACCOUNTS, TaskCategory.RECOMPUTATION, TaskCategory.RECONCILIATION, + TaskCategory.UTIL // this is a megahack: only utility tasks that count objects are DeleteTask and ShadowIntegrityCheck + ); + + private LoadableModel statisticsModel; + + public TaskOperationStatisticsPanel(String id, IModel> model) { + super(id, model); + + statisticsModel = createOperationStatsModel(); + } + + private LoadableModel createOperationStatsModel() { + + return new LoadableModel(true) { + + @Override + protected OperationStatsType load() { + PrismObject task = getModelObject().getObject(); + return TaskTypeUtil.getAggregatedOperationStats(task.asObjectable(), getPrismContext()); + } + }; + } + + @Override + protected void onInitialize() { + super.onInitialize(); + + initLayout(); + setOutputMarkupId(true); + } + + private void initLayout() { + + TaskIterativeInformationPanel infoPanel = new TaskIterativeInformationPanel(ID_PROCESSING_INFO, new PropertyModel<>(statisticsModel, OperationStatsType.F_ITERATIVE_TASK_INFORMATION.getLocalPart())) { + + + @Override + protected Long getWallClockAverage(int objectsTotal) { + if (objectsTotal == 0) { + return null; + } + + TaskType task = TaskOperationStatisticsPanel.this.getModelObject().getObject().asObjectable(); + if (!WALL_CLOCK_AVG_CATEGORIES.contains(task.getCategory())) { + return null; + } + + Long started = WebComponentUtil.xgc2long(task.getLastRunStartTimestamp()); + if (started == null) { + return null; + } + Long finished = WebComponentUtil.xgc2long(task.getLastRunFinishTimestamp()); + if (finished == null || finished < started) { + finished = System.currentTimeMillis(); + } + + return (finished - started) / objectsTotal; + } + }; + infoPanel.setOutputMarkupId(true); + add(infoPanel); + + + PropertyModel> syncInfoModel = new PropertyModel>(statisticsModel, "") { + + @Override + public List getObject() { + OperationStatsType statsType = statisticsModel.getObject(); + if (statsType == null) { + return null; + } + + SynchronizationInformationType syncInfo = statsType.getSynchronizationInformation(); + if(syncInfo == null) { + return null; + } + + List infos = new ArrayList<>(); + infos.add(new SynchronizationInformationDto("Unmatched",syncInfo.getCountUnmatched(), syncInfo.getCountUnmatchedAfter())); + infos.add(new SynchronizationInformationDto("Unlinked",syncInfo.getCountUnlinked(), syncInfo.getCountUnlinkedAfter())); + infos.add(new SynchronizationInformationDto("Linked",syncInfo.getCountLinked(), syncInfo.getCountLinkedAfter())); + infos.add(new SynchronizationInformationDto("Deleted",syncInfo.getCountDeleted(), syncInfo.getCountDeletedAfter())); + infos.add(new SynchronizationInformationDto("Disputed",syncInfo.getCountDisputed(), syncInfo.getCountDisputedAfter())); + infos.add(new SynchronizationInformationDto("Protected",syncInfo.getCountProtected(), syncInfo.getCountProtectedAfter())); + infos.add(new SynchronizationInformationDto("No sync policy",syncInfo.getCountNoSynchronizationPolicy(), syncInfo.getCountNoSynchronizationPolicyAfter())); + infos.add(new SynchronizationInformationDto("Sync disabled",syncInfo.getCountSynchronizationDisabled(), syncInfo.getCountSynchronizationDisabledAfter())); + infos.add(new SynchronizationInformationDto("Not applicable for task",syncInfo.getCountNotApplicableForTask(), syncInfo.getCountNotApplicableForTaskAfter())); + + return infos; + } + }; + + ListDataProvider syncDataProvider = new ListDataProvider(this, syncInfoModel) { + @Override + public boolean isUseCache() { + return false; + } + }; + + List> syncColumns = new ArrayList<>(); + syncColumns.add(new PropertyColumn<>(createStringResource("TaskOperationStatisticsPanel.situation"), SynchronizationInformationDto.F_ACTION_NAME)); + syncColumns.add(new PropertyColumn<>(createStringResource("TaskOperationStatisticsPanel.countBefore"), SynchronizationInformationDto.F_COUNT_BEFORE)); + syncColumns.add(new PropertyColumn<>(createStringResource("TaskOperationStatisticsPanel.countAfter"), SynchronizationInformationDto.F_COUNT_AFTER)); + + BoxedTablePanel table = new BoxedTablePanel(ID_SYNCHORNIZATION_SITUATIONS, syncDataProvider, syncColumns) { + @Override + protected boolean hideFooterIfSinglePage() { + return true; + } + }; + + table.setOutputMarkupId(true); + add(table); + + ListDataProvider objectActionsEntry = createActionsEntryProvider(OperationStatsType.F_ACTIONS_EXECUTED_INFORMATION.getLocalPart() + "." + ActionsExecutedInformationType.F_RESULTING_OBJECT_ACTIONS_ENTRY); + BoxedTablePanel actionTable = new BoxedTablePanel(ID_ACTION_ENTRY, objectActionsEntry, createActionEntryColumns()) { + @Override + protected boolean hideFooterIfSinglePage() { + return true; + } + }; + + actionTable.setOutputMarkupId(true); + add(actionTable); + + + BoxedTablePanel resultingEntry = new BoxedTablePanel(ID_RESULTING_ENTRY, createActionsEntryProvider(OperationStatsType.F_ACTIONS_EXECUTED_INFORMATION.getLocalPart() + "." + ActionsExecutedInformationType.F_OBJECT_ACTIONS_ENTRY), createActionEntryColumns()) { + @Override + protected boolean hideFooterIfSinglePage() { + return true; + } + }; + + resultingEntry.setOutputMarkupId(true); + add(resultingEntry); + + } + + private ListDataProvider createActionsEntryProvider(String expression) { + return new ListDataProvider<>(this, + new PropertyModel<>(statisticsModel, expression)); + } + + private List> createActionEntryColumns() { + List> resultingEntryColumns = new ArrayList<>(); + resultingEntryColumns.add(new AbstractColumn(createStringResource("ObjectActionsExecutedEntryType.objectType")) { + @Override + public void populateItem(Item> item, String id, IModel iModel) { + ObjectActionsExecutedEntryType entry = iModel.getObject(); + ObjectTypes objectType = null; + if (entry != null) { + if (entry.getObjectType() != null) { + objectType = ObjectTypes.getObjectTypeFromTypeQName(entry.getObjectType()); + } + } + item.add(new Label(id, createStringResource(objectType))); + } + }); + resultingEntryColumns.add(new EnumPropertyColumn<>(createStringResource("ObjectActionsExecutedEntryType.operation"), ObjectActionsExecutedEntryType.F_OPERATION.getLocalPart())); + resultingEntryColumns.add(new AbstractColumn(createStringResource("ObjectActionsExecutedEntryType.chanel")) { + @Override + public void populateItem(Item> item, String id, IModel iModel) { + String channel = iModel.getObject().getChannel(); + String key = ""; + if (channel != null && !channel.isEmpty()) { + key = "Channel." + WebComponentUtil.getSimpleChannel(channel); + } + item.add(new Label(id, createStringResource(key))); + } + }); + resultingEntryColumns.add(new PropertyColumn<>(createStringResource("ObjectActionsExecutedEntryType.totalSuccessCount"), ObjectActionsExecutedEntryType.F_TOTAL_SUCCESS_COUNT.getLocalPart())); + resultingEntryColumns.add(new PropertyColumn<>(createStringResource("ObjectActionsExecutedEntryType.lastSuccessDisplayName"), ObjectActionsExecutedEntryType.F_LAST_SUCCESS_OBJECT_DISPLAY_NAME.getLocalPart())); + resultingEntryColumns.add(new AbstractColumn(createStringResource("ObjectActionsExecutedEntryType.lastSuccessTimestamp")) { + @Override + public void populateItem(Item> item, String id, IModel iModel) { + XMLGregorianCalendar timestamp = iModel.getObject().getLastSuccessTimestamp(); + item.add(new Label(id, WebComponentUtil.formatDate(timestamp))); + } + }); + resultingEntryColumns.add(new PropertyColumn<>(createStringResource("ObjectActionsExecutedEntryType.totalFailureCount"), ObjectActionsExecutedEntryType.F_TOTAL_FAILURE_COUNT.getLocalPart())); + return resultingEntryColumns; + } + + @Override + public Collection getComponentsToUpdate() { + statisticsModel.reset(); + List components = new ArrayList<>(); + components.add(get(ID_ACTION_ENTRY)); + components.add(get(ID_PROCESSING_INFO)); + components.add(get(ID_RESULTING_ENTRY)); + components.add(get(ID_SYNCHORNIZATION_SITUATIONS)); + return components; + } + + class SynchronizationInformationDto implements Serializable { + + public static final String F_ACTION_NAME = "actionName"; + public static final String F_COUNT_BEFORE = "countBefore"; + public static final String F_COUNT_AFTER = "countAfter"; + + private String actionName; + private int countBefore; + private int countAfter; + + public SynchronizationInformationDto(String actionName, int countBefore, int countAfter) { + this.actionName = actionName; + this.countBefore = countBefore; + this.countAfter = countAfter; + } + + } + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskOperationTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskOperationTabPanel.java index 251d6a1aabd..3dd0eaf06ca 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskOperationTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskOperationTabPanel.java @@ -1,127 +1,127 @@ -/* - * Copyright (c) 2010-2017 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.page.admin.server; - -import java.util.Collection; -import java.util.Collections; - -import com.evolveum.midpoint.gui.api.component.BasePanel; - -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; - -import com.evolveum.midpoint.model.api.context.ModelContext; -import com.evolveum.midpoint.model.api.util.ModelContextUtil; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.LoggingUtils; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LensContextType; - -import org.apache.wicket.Component; -import org.apache.wicket.model.IModel; - -import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.model.operationStatus.ModelOperationStatusDto; -import com.evolveum.midpoint.web.component.model.operationStatus.ModelOperationStatusPanel; -import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; - -/** - * @author semancik - */ - -//TODO implement correctly -public class TaskOperationTabPanel extends BasePanel> implements RefreshableTabPanel { - private static final long serialVersionUID = 1L; - - private static final String ID_MODEL_OPERATION_STATUS_PANEL = "modelOperationStatusPanel"; - private static final String DOT_CLASS = TaskOperationTabPanel.class.getName() + "."; - private static final String OPERATION_LOAD_SCENE_DTO = DOT_CLASS + "loadSceneDto"; - - private static final Trace LOGGER = TraceManager.getTrace(TaskOperationTabPanel.class); - - - - public TaskOperationTabPanel(String id, IModel> modelContextModel) { - super(id, modelContextModel); - setOutputMarkupId(true); - } - - @Override - protected void onInitialize() { - super.onInitialize(); - initLayout(); - - } - - private LensContextType getLensContextType() { - try{ - LensContextType lensContextType = getModelObject().getValue().getRealValue(); - if (lensContextType.getState() == null) { - return null; - } - return lensContextType; - } catch (SchemaException e) { - LoggingUtils.logUnexpectedException(LOGGER, "Unexpected error, cannot get real value for model context", e, e.getMessage()); - return null; - } - } - - private void initLayout() { - final LensContextType lensContextType = getLensContextType(); - - LoadableModel operationStatusModel = null; - if (lensContextType != null) { - operationStatusModel = new LoadableModel() { - @Override - protected ModelOperationStatusDto load() { - Task task = getPageBase().createSimpleTask(OPERATION_LOAD_SCENE_DTO); - OperationResult result = task.getResult(); - - ModelContext ctx; - try { - ctx = ModelContextUtil.unwrapModelContext(lensContextType, getPageBase().getModelInteractionService(), task, result); - } catch (ObjectNotFoundException e) { - LoggingUtils.logUnexpectedException(LOGGER, "Unexpected error, cannot get real value for model context", e, e.getMessage()); - return null; - } - - return new ModelOperationStatusDto(ctx, getPageBase().getModelInteractionService(), task, result); - } - }; - } - - ModelOperationStatusPanel panel = new ModelOperationStatusPanel(ID_MODEL_OPERATION_STATUS_PANEL, operationStatusModel); - panel.add(new VisibleEnableBehaviour() { - @Override - public boolean isVisible() { - return lensContextType != null; - } - }); - add(panel); - } - - //TODO correc visibility - @Override - public boolean isVisible() { - try { - return getModelObject().getValue().getRealValue() != null && getModelObject().getValue().getRealValue().getState() != null; - } catch (SchemaException e) { - //TODO what to do? - } - - return false; - } - - @Override - public Collection getComponentsToUpdate() { - return Collections.singleton(this); - } - -} +/* + * Copyright (c) 2010-2017 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.page.admin.server; + +import java.util.Collection; +import java.util.Collections; + +import com.evolveum.midpoint.gui.api.component.BasePanel; + +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; + +import com.evolveum.midpoint.model.api.context.ModelContext; +import com.evolveum.midpoint.model.api.util.ModelContextUtil; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.LoggingUtils; +import com.evolveum.midpoint.xml.ns._public.common.common_3.LensContextType; + +import org.apache.wicket.Component; +import org.apache.wicket.model.IModel; + +import com.evolveum.midpoint.gui.api.model.LoadableModel; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.component.model.operationStatus.ModelOperationStatusDto; +import com.evolveum.midpoint.web.component.model.operationStatus.ModelOperationStatusPanel; +import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; + +/** + * @author semancik + */ + +//TODO implement correctly +public class TaskOperationTabPanel extends BasePanel> implements RefreshableTabPanel { + private static final long serialVersionUID = 1L; + + private static final String ID_MODEL_OPERATION_STATUS_PANEL = "modelOperationStatusPanel"; + private static final String DOT_CLASS = TaskOperationTabPanel.class.getName() + "."; + private static final String OPERATION_LOAD_SCENE_DTO = DOT_CLASS + "loadSceneDto"; + + private static final Trace LOGGER = TraceManager.getTrace(TaskOperationTabPanel.class); + + + + public TaskOperationTabPanel(String id, IModel> modelContextModel) { + super(id, modelContextModel); + setOutputMarkupId(true); + } + + @Override + protected void onInitialize() { + super.onInitialize(); + initLayout(); + + } + + private LensContextType getLensContextType() { + try{ + LensContextType lensContextType = getModelObject().getValue().getRealValue(); + if (lensContextType.getState() == null) { + return null; + } + return lensContextType; + } catch (SchemaException e) { + LoggingUtils.logUnexpectedException(LOGGER, "Unexpected error, cannot get real value for model context", e, e.getMessage()); + return null; + } + } + + private void initLayout() { + final LensContextType lensContextType = getLensContextType(); + + LoadableModel operationStatusModel = null; + if (lensContextType != null) { + operationStatusModel = new LoadableModel() { + @Override + protected ModelOperationStatusDto load() { + Task task = getPageBase().createSimpleTask(OPERATION_LOAD_SCENE_DTO); + OperationResult result = task.getResult(); + + ModelContext ctx; + try { + ctx = ModelContextUtil.unwrapModelContext(lensContextType, getPageBase().getModelInteractionService(), task, result); + } catch (ObjectNotFoundException e) { + LoggingUtils.logUnexpectedException(LOGGER, "Unexpected error, cannot get real value for model context", e, e.getMessage()); + return null; + } + + return new ModelOperationStatusDto(ctx, getPageBase().getModelInteractionService(), task, result); + } + }; + } + + ModelOperationStatusPanel panel = new ModelOperationStatusPanel(ID_MODEL_OPERATION_STATUS_PANEL, operationStatusModel); + panel.add(new VisibleEnableBehaviour() { + @Override + public boolean isVisible() { + return lensContextType != null; + } + }); + add(panel); + } + + //TODO correc visibility + @Override + public boolean isVisible() { + try { + return getModelObject().getValue().getRealValue() != null && getModelObject().getValue().getRealValue().getState() != null; + } catch (SchemaException e) { + //TODO what to do? + } + + return false; + } + + @Override + public Collection getComponentsToUpdate() { + return Collections.singleton(this); + } + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskPerformanceTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskPerformanceTabPanel.java index 167259272c4..561c754d642 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskPerformanceTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskPerformanceTabPanel.java @@ -1,56 +1,56 @@ -/* - * Copyright (c) 2010-2017 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.page.admin.server; - -import java.util.Collection; -import java.util.Collections; - -import com.evolveum.midpoint.gui.api.component.BasePanel; - -import org.apache.wicket.Component; - -import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.component.progress.StatisticsDtoModel; -import com.evolveum.midpoint.web.component.progress.StatisticsPanel; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; - -/** - * @author semancik - */ -public class TaskPerformanceTabPanel extends BasePanel> implements RefreshableTabPanel { - private static final long serialVersionUID = 1L; - - private static final String ID_STATISTICS_PANEL = "statisticsPanel"; - - private static final Trace LOGGER = TraceManager.getTrace(TaskPerformanceTabPanel.class); - - public TaskPerformanceTabPanel(String id, LoadableModel> taskWrapperModel) { - super(id, taskWrapperModel); - setOutputMarkupId(true); - } - - @Override - protected void onInitialize() { - super.onInitialize(); - initLayout(); - } - - private void initLayout() { - StatisticsDtoModel statisticsDtoModel = new StatisticsDtoModel(getModel()); - StatisticsPanel statisticsPanel = new StatisticsPanel(ID_STATISTICS_PANEL, statisticsDtoModel); - add(statisticsPanel); - } - - @Override - public Collection getComponentsToUpdate() { - return Collections.singleton(this); - } - -} +/* + * Copyright (c) 2010-2017 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.page.admin.server; + +import java.util.Collection; +import java.util.Collections; + +import com.evolveum.midpoint.gui.api.component.BasePanel; + +import org.apache.wicket.Component; + +import com.evolveum.midpoint.gui.api.model.LoadableModel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.component.progress.StatisticsDtoModel; +import com.evolveum.midpoint.web.component.progress.StatisticsPanel; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; + +/** + * @author semancik + */ +public class TaskPerformanceTabPanel extends BasePanel> implements RefreshableTabPanel { + private static final long serialVersionUID = 1L; + + private static final String ID_STATISTICS_PANEL = "statisticsPanel"; + + private static final Trace LOGGER = TraceManager.getTrace(TaskPerformanceTabPanel.class); + + public TaskPerformanceTabPanel(String id, LoadableModel> taskWrapperModel) { + super(id, taskWrapperModel); + setOutputMarkupId(true); + } + + @Override + protected void onInitialize() { + super.onInitialize(); + initLayout(); + } + + private void initLayout() { + StatisticsDtoModel statisticsDtoModel = new StatisticsDtoModel(getModel()); + StatisticsPanel statisticsPanel = new StatisticsPanel(ID_STATISTICS_PANEL, statisticsDtoModel); + add(statisticsPanel); + } + + @Override + public Collection getComponentsToUpdate() { + return Collections.singleton(this); + } + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskResultTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskResultTabPanel.java index 866e1006c70..e8ae32d2cb3 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskResultTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskResultTabPanel.java @@ -11,7 +11,7 @@ import com.evolveum.midpoint.gui.api.component.result.OperationResultPanel; import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.model.ReadOnlyModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.schema.result.OperationResult; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskSubtasksAndThreadsTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskSubtasksAndThreadsTabPanel.java index 7d5edf717ac..e2ca9062574 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskSubtasksAndThreadsTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskSubtasksAndThreadsTabPanel.java @@ -1,177 +1,177 @@ -/* - * Copyright (c) 2010-2017 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.page.admin.server; - -import com.evolveum.midpoint.gui.api.component.BasePanel; -import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.prism.*; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.schema.GetOperationOptions; -import com.evolveum.midpoint.schema.GetOperationOptionsBuilder; -import com.evolveum.midpoint.schema.SelectorOptions; -import com.evolveum.midpoint.web.component.data.BaseSortableDataProvider; -import com.evolveum.midpoint.web.component.data.column.EnumPropertyColumn; -import com.evolveum.midpoint.web.component.util.SelectableBean; -import com.evolveum.midpoint.web.component.util.SelectableBeanImpl; -import com.evolveum.midpoint.web.component.util.SelectableListDataProvider; -import com.evolveum.midpoint.web.session.UserProfileStorage; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskWorkManagementType; -import org.apache.wicket.Component; -import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; -import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.markup.html.basic.Label; -import org.apache.wicket.model.*; - -import javax.xml.namespace.QName; -import java.util.*; - -/** - * @author semancik - */ -public class TaskSubtasksAndThreadsTabPanel extends BasePanel> implements RefreshableTabPanel { - private static final long serialVersionUID = 1L; - - private static final String ID_WORKER_THREADS_TABLE = "workerThreadsTable"; - private static final String ID_WORKER_THREADS_TABLE_LABEL = "workerThreadsTableLabel"; - - private static final String ID_SUBTASKS_LABEL = "subtasksLabel"; - private static final String ID_SUBTASKS_PANEL = "subtasksPanel"; - - - public TaskSubtasksAndThreadsTabPanel(String id, - LoadableModel> taskWrapperModel) { - super(id, taskWrapperModel); - setOutputMarkupId(true); - } - - @Override - protected void onInitialize() { - super.onInitialize(); - initLayout(); - } - - private String createTaskKindExpression() { - return SelectableBeanImpl.F_VALUE + "." + TaskType.F_WORK_MANAGEMENT.getLocalPart() + "." + TaskWorkManagementType.F_TASK_KIND.getLocalPart(); - } - private void initLayout() { - Label subtasksLabel = new Label(ID_SUBTASKS_LABEL, new ResourceModel("pageTaskEdit.subtasksLabel")); - add(subtasksLabel); - - TaskTablePanel subtasksPanel = new TaskTablePanel(ID_SUBTASKS_PANEL, UserProfileStorage.TableId.TABLE_SUBTASKS, createOperationOptions()) { - @Override - protected ObjectQuery addFilterToContentQuery(ObjectQuery query) { - - String parent = getParentIdentifier(); - if (parent == null) { - return query; - } - - if (query == null) { - query = getPrismContext().queryFactory().createQuery(); - } - - query.addFilter(getPrismContext().queryFor(TaskType.class) - .item(TaskType.F_PARENT) - .eq(parent) - .buildFilter()); - - return query; - } - - @Override - protected List, String>> createColumns() { - List, String>> columns = super.createColumns(); - columns.add(2, new EnumPropertyColumn>(createStringResource("SubtasksPanel.label.kind"), createTaskKindExpression()) { - - @Override - protected String translate(Enum en) { - return createStringResource(en).getString(); - } - }); - return columns; - } - - @Override - protected WebMarkupContainer createTableButtonToolbar(String id) { - return null; - } - }; - - add(subtasksPanel); - - Label workerThreadsTableLabel = new Label(ID_WORKER_THREADS_TABLE_LABEL, new ResourceModel("TaskStatePanel.workerThreads")); - add(workerThreadsTableLabel); - - TaskTablePanel workerThreadsTable = new TaskTablePanel(ID_WORKER_THREADS_TABLE, UserProfileStorage.TableId.TABLE_WORKERS, null) { - - @Override - protected BaseSortableDataProvider> initProvider() { - return new SelectableListDataProvider<>(TaskSubtasksAndThreadsTabPanel.this, createWorkersModel()); - } - - @Override - protected WebMarkupContainer createTableButtonToolbar(String id) { - return null; - } - - @Override - protected boolean isHeaderVisible() { - return false; - } - }; - add(workerThreadsTable); - } - - private Collection> createOperationOptions() { - List propertiesToGet = new ArrayList<>(); - propertiesToGet.add(TaskType.F_SUBTASK_REF); - - GetOperationOptionsBuilder getOperationOptionsBuilder = getSchemaHelper().getOperationOptionsBuilder(); - getOperationOptionsBuilder = getOperationOptionsBuilder.resolveNames(); - Collection> searchOptions = getOperationOptionsBuilder - .items(propertiesToGet.toArray(new Object[0])).retrieve() - .build(); - return searchOptions; - } - - private IModel> createWorkersModel() { - return (IModel>) () -> { - PrismObject taskPrism = TaskSubtasksAndThreadsTabPanel.this.getModelObject().getObject(); - PrismReference subtasks = taskPrism.findReference(TaskType.F_SUBTASK_REF); - - if (subtasks == null) { - return new ArrayList<>(); - } - - List workers = new ArrayList<>(); - for (PrismReferenceValue val : subtasks.getValues()) { - if (val.getOid() == null && val.getObject() != null) { - workers.add((TaskType) val.getObject().asObjectable()); - } - } - return workers; - }; - } - - private String getParentIdentifier() { - PrismObject taskPrism = getModelObject().getObject(); - PrismProperty taskIdentifier = taskPrism.findProperty(TaskType.F_TASK_IDENTIFIER); - if (taskIdentifier == null) { - return null; //TODO is this valid? - } - - return taskIdentifier.getRealValue(); - } - - @Override - public Collection getComponentsToUpdate() { - return Collections.singleton(this); - } - -} +/* + * Copyright (c) 2010-2017 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.page.admin.server; + +import com.evolveum.midpoint.gui.api.component.BasePanel; +import com.evolveum.midpoint.gui.api.model.LoadableModel; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.GetOperationOptionsBuilder; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.web.component.data.BaseSortableDataProvider; +import com.evolveum.midpoint.web.component.data.column.EnumPropertyColumn; +import com.evolveum.midpoint.web.component.util.SelectableBean; +import com.evolveum.midpoint.web.component.util.SelectableBeanImpl; +import com.evolveum.midpoint.web.component.util.SelectableListDataProvider; +import com.evolveum.midpoint.web.session.UserProfileStorage; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskWorkManagementType; +import org.apache.wicket.Component; +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.model.*; + +import javax.xml.namespace.QName; +import java.util.*; + +/** + * @author semancik + */ +public class TaskSubtasksAndThreadsTabPanel extends BasePanel> implements RefreshableTabPanel { + private static final long serialVersionUID = 1L; + + private static final String ID_WORKER_THREADS_TABLE = "workerThreadsTable"; + private static final String ID_WORKER_THREADS_TABLE_LABEL = "workerThreadsTableLabel"; + + private static final String ID_SUBTASKS_LABEL = "subtasksLabel"; + private static final String ID_SUBTASKS_PANEL = "subtasksPanel"; + + + public TaskSubtasksAndThreadsTabPanel(String id, + LoadableModel> taskWrapperModel) { + super(id, taskWrapperModel); + setOutputMarkupId(true); + } + + @Override + protected void onInitialize() { + super.onInitialize(); + initLayout(); + } + + private String createTaskKindExpression() { + return SelectableBeanImpl.F_VALUE + "." + TaskType.F_WORK_MANAGEMENT.getLocalPart() + "." + TaskWorkManagementType.F_TASK_KIND.getLocalPart(); + } + private void initLayout() { + Label subtasksLabel = new Label(ID_SUBTASKS_LABEL, new ResourceModel("pageTaskEdit.subtasksLabel")); + add(subtasksLabel); + + TaskTablePanel subtasksPanel = new TaskTablePanel(ID_SUBTASKS_PANEL, UserProfileStorage.TableId.TABLE_SUBTASKS, createOperationOptions()) { + @Override + protected ObjectQuery addFilterToContentQuery(ObjectQuery query) { + + String parent = getParentIdentifier(); + if (parent == null) { + return query; + } + + if (query == null) { + query = getPrismContext().queryFactory().createQuery(); + } + + query.addFilter(getPrismContext().queryFor(TaskType.class) + .item(TaskType.F_PARENT) + .eq(parent) + .buildFilter()); + + return query; + } + + @Override + protected List, String>> createColumns() { + List, String>> columns = super.createColumns(); + columns.add(2, new EnumPropertyColumn>(createStringResource("SubtasksPanel.label.kind"), createTaskKindExpression()) { + + @Override + protected String translate(Enum en) { + return createStringResource(en).getString(); + } + }); + return columns; + } + + @Override + protected WebMarkupContainer createTableButtonToolbar(String id) { + return null; + } + }; + + add(subtasksPanel); + + Label workerThreadsTableLabel = new Label(ID_WORKER_THREADS_TABLE_LABEL, new ResourceModel("TaskStatePanel.workerThreads")); + add(workerThreadsTableLabel); + + TaskTablePanel workerThreadsTable = new TaskTablePanel(ID_WORKER_THREADS_TABLE, UserProfileStorage.TableId.TABLE_WORKERS, null) { + + @Override + protected BaseSortableDataProvider> initProvider() { + return new SelectableListDataProvider<>(TaskSubtasksAndThreadsTabPanel.this, createWorkersModel()); + } + + @Override + protected WebMarkupContainer createTableButtonToolbar(String id) { + return null; + } + + @Override + protected boolean isHeaderVisible() { + return false; + } + }; + add(workerThreadsTable); + } + + private Collection> createOperationOptions() { + List propertiesToGet = new ArrayList<>(); + propertiesToGet.add(TaskType.F_SUBTASK_REF); + + GetOperationOptionsBuilder getOperationOptionsBuilder = getSchemaHelper().getOperationOptionsBuilder(); + getOperationOptionsBuilder = getOperationOptionsBuilder.resolveNames(); + Collection> searchOptions = getOperationOptionsBuilder + .items(propertiesToGet.toArray(new Object[0])).retrieve() + .build(); + return searchOptions; + } + + private IModel> createWorkersModel() { + return (IModel>) () -> { + PrismObject taskPrism = TaskSubtasksAndThreadsTabPanel.this.getModelObject().getObject(); + PrismReference subtasks = taskPrism.findReference(TaskType.F_SUBTASK_REF); + + if (subtasks == null) { + return new ArrayList<>(); + } + + List workers = new ArrayList<>(); + for (PrismReferenceValue val : subtasks.getValues()) { + if (val.getOid() == null && val.getObject() != null) { + workers.add((TaskType) val.getObject().asObjectable()); + } + } + return workers; + }; + } + + private String getParentIdentifier() { + PrismObject taskPrism = getModelObject().getObject(); + PrismProperty taskIdentifier = taskPrism.findProperty(TaskType.F_TASK_IDENTIFIER); + if (taskIdentifier == null) { + return null; //TODO is this valid? + } + + return taskIdentifier.getRealValue(); + } + + @Override + public Collection getComponentsToUpdate() { + return Collections.singleton(this); + } + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskTabsVisibility.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskTabsVisibility.java index 434dfc08df9..9e70a4e662d 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskTabsVisibility.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskTabsVisibility.java @@ -6,26 +6,18 @@ */ package com.evolveum.midpoint.web.page.admin.server; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.impl.prism.PrismReferenceWrapper; import com.evolveum.midpoint.model.api.ModelPublicConstants; -import com.evolveum.midpoint.prism.PrismReference; -import com.evolveum.midpoint.prism.PrismReferenceValue; -import com.evolveum.midpoint.prism.Referencable; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.statistics.StatisticsUtil; -import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang.StringUtils; import java.io.Serializable; import java.util.List; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/services/PageServiceHistory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/services/PageServiceHistory.java index 5a5ee96f796..80a5e45fe25 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/services/PageServiceHistory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/services/PageServiceHistory.java @@ -7,7 +7,7 @@ package com.evolveum.midpoint.web.page.admin.services; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.security.api.AuthorizationConstants; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/PageMergeObjects.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/PageMergeObjects.java index eb456ae79b8..de21d07e603 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/PageMergeObjects.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/PageMergeObjects.java @@ -1,240 +1,238 @@ -/* - * Copyright (c) 2010-2017 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.page.admin.users; - -import com.evolveum.midpoint.gui.api.component.tabs.PanelTab; -import com.evolveum.midpoint.gui.api.model.CountableLoadableModel; -import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.ShadowWrapper; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.security.api.AuthorizationConstants; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.logging.LoggingUtils; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.application.AuthorizationAction; -import com.evolveum.midpoint.web.application.PageDescriptor; -import com.evolveum.midpoint.web.component.FocusSummaryPanel; -import com.evolveum.midpoint.web.component.ObjectSummaryPanel; -import com.evolveum.midpoint.web.component.objectdetails.AbstractObjectMainPanel; -import com.evolveum.midpoint.web.component.objectdetails.FocusMainPanel; -import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; -import com.evolveum.midpoint.web.page.admin.PageAdminFocus; -import com.evolveum.midpoint.web.page.admin.PageAdminObjectDetails; -import com.evolveum.midpoint.web.page.admin.users.component.MergeObjectsPanel; -import com.evolveum.midpoint.web.page.admin.users.component.UserSummaryPanel; -import com.evolveum.midpoint.web.util.OnePageParameterEncoder; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.extensions.markup.html.tabs.ITab; -import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.model.IModel; -import org.apache.wicket.request.mapper.parameter.PageParameters; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by honchar. - */ -@PageDescriptor(url = "/admin/mergeObjects", encoder = OnePageParameterEncoder.class, action = { - @AuthorizationAction(actionUri = AuthorizationConstants.AUTZ_UI_USERS_ALL_URL, - label = "PageAdminUsers.auth.usersAll.label", - description = "PageAdminUsers.auth.usersAll.description"), - @AuthorizationAction(actionUri = AuthorizationConstants.AUTZ_UI_USER_URL, - label = "PageUser.auth.user.label", - description = "PageUser.auth.user.description"), - @AuthorizationAction(actionUri = AuthorizationConstants.AUTZ_UI_MERGE_OBJECTS_URL, - label = "PageMergeObjects.auth.mergeObjects.label", - description = "PageMergeObjects.auth.mergeObjects.description") }) -public class PageMergeObjects extends PageAdminFocus { - private static final long serialVersionUID = 1L; - - private static final String DOT_CLASS = PageMergeObjects.class.getName() + "."; - private static final String OPERATION_DELETE_USER = DOT_CLASS + "deleteUser"; - private static final String OPERATION_MERGE_OBJECTS = DOT_CLASS + "mergeObjects"; - private static final Trace LOGGER = TraceManager.getTrace(PageMergeObjects.class); - private F mergeObject; - private IModel mergeObjectModel; - private F mergeWithObject; - private IModel mergeWithObjectModel; - private Class type; - private MergeObjectsPanel mergeObjectsPanel; - - public PageMergeObjects(){ - } - - public PageMergeObjects(F mergeObject, F mergeWithObject, Class type){ - this.mergeObject = mergeObject; - this.mergeWithObject = mergeWithObject; - this.type = type; - - initModels(); - - PageParameters parameters = new PageParameters(); - parameters.add(OnePageParameterEncoder.PARAMETER, mergeObject.getOid()); - getPageParameters().overwriteWith(parameters); - initialize(this.mergeObject.asPrismObject()); - } - - private void initModels(){ - mergeObjectModel = new IModel() { - @Override - public F getObject() { - return mergeObject; - } - - @Override - public void setObject(F f) { - mergeObject = f; - } - - @Override - public void detach() { - - } - }; - mergeWithObjectModel = new IModel() { - @Override - public F getObject() { - return mergeWithObject; - } - - @Override - public void setObject(F f) { - mergeWithObject = f; - } - - @Override - public void detach() { - - } - }; - } - - @Override - protected AbstractObjectMainPanel createMainPanel(String id){ - - //empty assignments model - CountableLoadableModel assignemtns = new CountableLoadableModel() { - private static final long serialVersionUID = 1L; - - @Override - protected List load() { - return new ArrayList<>(); - } - }; - - //empty policy rules model - CountableLoadableModel policyRules = new CountableLoadableModel() { - private static final long serialVersionUID = 1L; - - @Override - protected List load() { - return new ArrayList<>(); - } - }; - - //empty projections model - LoadableModel> shadows = new LoadableModel>() { - private static final long serialVersionUID = 1L; - @Override - protected List load() { - return new ArrayList<>(); - } - }; - - return new FocusMainPanel(id, getObjectModel(), shadows, this) { - - private static final long serialVersionUID = 1L; - - @Override - protected List createTabs(final PageAdminObjectDetails parentPage) { - List tabs = new ArrayList<>(); - tabs.add( - new PanelTab(parentPage.createStringResource("PageMergeObjects.tabTitle"), new VisibleEnableBehaviour()){ - private static final long serialVersionUID = 1L; - - @Override - public WebMarkupContainer createPanel(String panelId) { - mergeObjectsPanel = new MergeObjectsPanel(panelId, mergeObjectModel, mergeWithObjectModel, type, PageMergeObjects.this); - return mergeObjectsPanel; - } - }); - return tabs; - } - - @Override - protected boolean isPreviewButtonVisible(){ - return false; - } - - @Override - protected boolean getOptionsPanelVisibility() { - return false; - } - }; - } - - - //TODO did it work before? - @Override - protected ObjectSummaryPanel createSummaryPanel(IModel summaryModel) { - UserSummaryPanel summaryPanel = new UserSummaryPanel(ID_SUMMARY_PANEL, getObjectModel(), this); - return summaryPanel; - } - - @Override - protected void setSummaryPanelVisibility(ObjectSummaryPanel summaryPanel){ - summaryPanel.setVisible(false); - } - - @Override - protected Class getRestartResponsePage() { - return PageUsers.class; - } - - protected UserType createNewObject(){ - return new UserType(); - } - - @Override - public Class getCompileTimeClass() { - return type; - } - - @Override - protected IModel createPageTitleModel() { - return createStringResource("PageMergeObjects.title"); - } - - @Override - public boolean isOidParameterExists() { - return true; - } - - @Override - public void saveOrPreviewPerformed(AjaxRequestTarget target, OperationResult result, boolean previewOnly) { - try { - Task task = createSimpleTask(OPERATION_MERGE_OBJECTS); - getModelService().mergeObjects(type, mergeObject.getOid(), mergeWithObject.getOid(), - mergeObjectsPanel.getMergeConfigurationName(), task, result); - result.computeStatusIfUnknown(); - showResult(result); - redirectBack(); - - } catch (Exception ex){ - result.recomputeStatus(); - result.recordFatalError(getString("PageMergeObjects.message.saveOrPreviewPerformed.fatalError"), ex); - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't merge objects", ex); - showResult(result); - } - } -} +/* + * Copyright (c) 2010-2017 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.page.admin.users; + +import com.evolveum.midpoint.gui.api.component.tabs.PanelTab; +import com.evolveum.midpoint.gui.api.model.CountableLoadableModel; +import com.evolveum.midpoint.gui.api.model.LoadableModel; +import com.evolveum.midpoint.gui.api.prism.wrapper.ShadowWrapper; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.security.api.AuthorizationConstants; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.logging.LoggingUtils; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.application.AuthorizationAction; +import com.evolveum.midpoint.web.application.PageDescriptor; +import com.evolveum.midpoint.web.component.ObjectSummaryPanel; +import com.evolveum.midpoint.web.component.objectdetails.AbstractObjectMainPanel; +import com.evolveum.midpoint.web.component.objectdetails.FocusMainPanel; +import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; +import com.evolveum.midpoint.web.page.admin.PageAdminFocus; +import com.evolveum.midpoint.web.page.admin.PageAdminObjectDetails; +import com.evolveum.midpoint.web.page.admin.users.component.MergeObjectsPanel; +import com.evolveum.midpoint.web.page.admin.users.component.UserSummaryPanel; +import com.evolveum.midpoint.web.util.OnePageParameterEncoder; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.extensions.markup.html.tabs.ITab; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.model.IModel; +import org.apache.wicket.request.mapper.parameter.PageParameters; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by honchar. + */ +@PageDescriptor(url = "/admin/mergeObjects", encoder = OnePageParameterEncoder.class, action = { + @AuthorizationAction(actionUri = AuthorizationConstants.AUTZ_UI_USERS_ALL_URL, + label = "PageAdminUsers.auth.usersAll.label", + description = "PageAdminUsers.auth.usersAll.description"), + @AuthorizationAction(actionUri = AuthorizationConstants.AUTZ_UI_USER_URL, + label = "PageUser.auth.user.label", + description = "PageUser.auth.user.description"), + @AuthorizationAction(actionUri = AuthorizationConstants.AUTZ_UI_MERGE_OBJECTS_URL, + label = "PageMergeObjects.auth.mergeObjects.label", + description = "PageMergeObjects.auth.mergeObjects.description") }) +public class PageMergeObjects extends PageAdminFocus { + private static final long serialVersionUID = 1L; + + private static final String DOT_CLASS = PageMergeObjects.class.getName() + "."; + private static final String OPERATION_DELETE_USER = DOT_CLASS + "deleteUser"; + private static final String OPERATION_MERGE_OBJECTS = DOT_CLASS + "mergeObjects"; + private static final Trace LOGGER = TraceManager.getTrace(PageMergeObjects.class); + private F mergeObject; + private IModel mergeObjectModel; + private F mergeWithObject; + private IModel mergeWithObjectModel; + private Class type; + private MergeObjectsPanel mergeObjectsPanel; + + public PageMergeObjects(){ + } + + public PageMergeObjects(F mergeObject, F mergeWithObject, Class type){ + this.mergeObject = mergeObject; + this.mergeWithObject = mergeWithObject; + this.type = type; + + initModels(); + + PageParameters parameters = new PageParameters(); + parameters.add(OnePageParameterEncoder.PARAMETER, mergeObject.getOid()); + getPageParameters().overwriteWith(parameters); + initialize(this.mergeObject.asPrismObject()); + } + + private void initModels(){ + mergeObjectModel = new IModel() { + @Override + public F getObject() { + return mergeObject; + } + + @Override + public void setObject(F f) { + mergeObject = f; + } + + @Override + public void detach() { + + } + }; + mergeWithObjectModel = new IModel() { + @Override + public F getObject() { + return mergeWithObject; + } + + @Override + public void setObject(F f) { + mergeWithObject = f; + } + + @Override + public void detach() { + + } + }; + } + + @Override + protected AbstractObjectMainPanel createMainPanel(String id){ + + //empty assignments model + CountableLoadableModel assignemtns = new CountableLoadableModel() { + private static final long serialVersionUID = 1L; + + @Override + protected List load() { + return new ArrayList<>(); + } + }; + + //empty policy rules model + CountableLoadableModel policyRules = new CountableLoadableModel() { + private static final long serialVersionUID = 1L; + + @Override + protected List load() { + return new ArrayList<>(); + } + }; + + //empty projections model + LoadableModel> shadows = new LoadableModel>() { + private static final long serialVersionUID = 1L; + @Override + protected List load() { + return new ArrayList<>(); + } + }; + + return new FocusMainPanel(id, getObjectModel(), shadows, this) { + + private static final long serialVersionUID = 1L; + + @Override + protected List createTabs(final PageAdminObjectDetails parentPage) { + List tabs = new ArrayList<>(); + tabs.add( + new PanelTab(parentPage.createStringResource("PageMergeObjects.tabTitle"), new VisibleEnableBehaviour()){ + private static final long serialVersionUID = 1L; + + @Override + public WebMarkupContainer createPanel(String panelId) { + mergeObjectsPanel = new MergeObjectsPanel(panelId, mergeObjectModel, mergeWithObjectModel, type, PageMergeObjects.this); + return mergeObjectsPanel; + } + }); + return tabs; + } + + @Override + protected boolean isPreviewButtonVisible(){ + return false; + } + + @Override + protected boolean getOptionsPanelVisibility() { + return false; + } + }; + } + + + //TODO did it work before? + @Override + protected ObjectSummaryPanel createSummaryPanel(IModel summaryModel) { + UserSummaryPanel summaryPanel = new UserSummaryPanel(ID_SUMMARY_PANEL, getObjectModel(), this); + return summaryPanel; + } + + @Override + protected void setSummaryPanelVisibility(ObjectSummaryPanel summaryPanel){ + summaryPanel.setVisible(false); + } + + @Override + protected Class getRestartResponsePage() { + return PageUsers.class; + } + + protected UserType createNewObject(){ + return new UserType(); + } + + @Override + public Class getCompileTimeClass() { + return type; + } + + @Override + protected IModel createPageTitleModel() { + return createStringResource("PageMergeObjects.title"); + } + + @Override + public boolean isOidParameterExists() { + return true; + } + + @Override + public void saveOrPreviewPerformed(AjaxRequestTarget target, OperationResult result, boolean previewOnly) { + try { + Task task = createSimpleTask(OPERATION_MERGE_OBJECTS); + getModelService().mergeObjects(type, mergeObject.getOid(), mergeWithObject.getOid(), + mergeObjectsPanel.getMergeConfigurationName(), task, result); + result.computeStatusIfUnknown(); + showResult(result); + redirectBack(); + + } catch (Exception ex){ + result.recomputeStatus(); + result.recordFatalError(getString("PageMergeObjects.message.saveOrPreviewPerformed.fatalError"), ex); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't merge objects", ex); + showResult(result); + } + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/PageOrgUnitHistory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/PageOrgUnitHistory.java index 95ee0982cfb..af484dcb81e 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/PageOrgUnitHistory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/PageOrgUnitHistory.java @@ -9,7 +9,7 @@ import org.apache.wicket.model.IModel; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.security.api.AuthorizationConstants; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/PageUserHistory.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/PageUserHistory.java index 40b52f4c7f9..54f82f03691 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/PageUserHistory.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/PageUserHistory.java @@ -8,7 +8,7 @@ package com.evolveum.midpoint.web.page.admin.users; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.security.api.AuthorizationConstants; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/TreeTablePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/TreeTablePanel.java index e182b582587..f94599bf57a 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/TreeTablePanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/component/TreeTablePanel.java @@ -27,11 +27,11 @@ import com.evolveum.midpoint.gui.api.component.BasePanel; import com.evolveum.midpoint.gui.api.page.PageBase; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.ModelServiceLocator; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.model.api.ModelAuthorizationAction; import com.evolveum.midpoint.model.api.ModelExecuteOptions; import com.evolveum.midpoint.prism.PrismContext; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/dto/FocusSubwrapperDto.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/dto/FocusSubwrapperDto.java index f220981c6d6..7e29aea8260 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/dto/FocusSubwrapperDto.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/users/dto/FocusSubwrapperDto.java @@ -11,7 +11,7 @@ import org.apache.commons.lang.Validate; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/valuePolicy/PageValuePolicy.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/valuePolicy/PageValuePolicy.java index 324e326e972..c3a3b450650 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/valuePolicy/PageValuePolicy.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/valuePolicy/PageValuePolicy.java @@ -21,11 +21,11 @@ import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.page.PageBase; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.schema.result.OperationResult; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/valuePolicy/component/ValuePolicyBasicPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/valuePolicy/component/ValuePolicyBasicPanel.java index 7e87cc5bac2..0f989abddff 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/valuePolicy/component/ValuePolicyBasicPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/valuePolicy/component/ValuePolicyBasicPanel.java @@ -10,7 +10,7 @@ import java.util.List; import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.web.component.form.Form; import com.evolveum.midpoint.web.component.objectdetails.AbstractObjectTabPanel; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/workflow/PageAttorneySelection.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/workflow/PageAttorneySelection.java index b3ab0d741ab..bb1bb0162aa 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/workflow/PageAttorneySelection.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/workflow/PageAttorneySelection.java @@ -28,6 +28,7 @@ import com.evolveum.midpoint.web.page.admin.users.PageUsers; import com.evolveum.midpoint.web.page.error.PageError; import com.evolveum.midpoint.web.session.UserProfileStorage; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import org.apache.wicket.RestartResponseException; import org.apache.wicket.ajax.AjaxRequestTarget; @@ -109,7 +110,7 @@ protected IColumn, String> createCheckboxColumn() { } @Override - protected IColumn, String> createNameColumn(IModel columnNameModel, String itemPath) { + protected IColumn, String> createNameColumn(IModel columnNameModel, String itemPath, ExpressionType expression) { return new ObjectNameColumn(createStringResource("ObjectType.name")) { private static final long serialVersionUID = 1L; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PagePostAuthentication.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PagePostAuthentication.java index e495c2b53a6..3192664dd17 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PagePostAuthentication.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/self/PagePostAuthentication.java @@ -20,10 +20,10 @@ import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismObjectDefinition; import com.evolveum.midpoint.prism.delta.ObjectDelta; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/BasicWebSecurityConfig.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/BasicWebSecurityConfig.java index 3354c5e0813..b7f2e2900fa 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/BasicWebSecurityConfig.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/BasicWebSecurityConfig.java @@ -16,10 +16,10 @@ import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.security.factory.channel.AuthChannelRegistryImpl; +import com.evolveum.midpoint.web.security.factory.module.AuthModuleRegistryImpl; import com.evolveum.midpoint.web.security.filter.MidpointAnonymousAuthenticationFilter; import com.evolveum.midpoint.web.security.filter.MidpointRequestAttributeAuthenticationFilter; import com.evolveum.midpoint.web.security.filter.configurers.AuthFilterConfigurer; -import com.evolveum.midpoint.web.security.factory.module.AuthModuleRegistryImpl; import org.jasig.cas.client.session.SingleSignOutFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -58,7 +58,6 @@ /** * @author skublik */ - @Order(SecurityProperties.BASIC_AUTH_ORDER - 1) @Configuration @EnableWebSecurity @@ -83,7 +82,7 @@ public class BasicWebSecurityConfig extends WebSecurityConfigurerAdapter { private ObjectPostProcessor objectObjectPostProcessor; - public BasicWebSecurityConfig(){ + public BasicWebSecurityConfig() { super(true); } @@ -186,7 +185,6 @@ protected void configure(HttpSecurity http) throws Exception { .securityContext(); http.apply(new AuthFilterConfigurer()); - http.sessionManagement() .maximumSessions(-1) .sessionRegistry(sessionRegistry) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/PageUrlMapping.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/PageUrlMapping.java index 64539d83f8e..81141c75875 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/PageUrlMapping.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/PageUrlMapping.java @@ -94,6 +94,10 @@ public enum PageUrlMapping { REST("/ws/rest/**", new DisplayableValue[]{ new AuthorizationActionValue(AUTZ_REST_ALL_URL, "RestEndpoint.authRest.all.label", "RestEndpoint.authRest.all.description") + }), + REST2("/rest2/**", new DisplayableValue[]{ + new AuthorizationActionValue(AUTZ_REST_ALL_URL, + "RestEndpoint.authRest.all.label", "RestEndpoint.authRest.all.description") }); private String url; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/SamlAuthenticationEntryPoint.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/SamlAuthenticationEntryPoint.java index 4da8f4b02c0..6307f3a3c94 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/SamlAuthenticationEntryPoint.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/SamlAuthenticationEntryPoint.java @@ -1,30 +1,30 @@ /* - * Copyright (c) 2010-2019 Evolveum and contributors + * Copyright (c) 2010-2020 Evolveum and contributors * * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ package com.evolveum.midpoint.web.security; -import com.evolveum.midpoint.model.api.authentication.MidpointAuthentication; -import com.evolveum.midpoint.model.api.authentication.ModuleAuthentication; -import com.evolveum.midpoint.web.security.module.authentication.Saml2ModuleAuthentication; -import com.evolveum.midpoint.web.security.util.IdentityProvider; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContextHolder; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; +import com.evolveum.midpoint.model.api.authentication.MidpointAuthentication; +import com.evolveum.midpoint.model.api.authentication.ModuleAuthentication; +import com.evolveum.midpoint.web.security.module.authentication.Saml2ModuleAuthentication; +import com.evolveum.midpoint.web.security.util.IdentityProvider; /** * @author skublik */ - public class SamlAuthenticationEntryPoint extends WicketLoginUrlAuthenticationEntryPoint { public SamlAuthenticationEntryPoint(String loginFormUrl) { @@ -38,9 +38,9 @@ public void commence(HttpServletRequest request, HttpServletResponse response, A if (authentication instanceof MidpointAuthentication) { MidpointAuthentication mpAuthentication = (MidpointAuthentication) authentication; ModuleAuthentication moduleAuthentication = mpAuthentication.getProcessingModuleAuthentication(); - if (moduleAuthentication != null && moduleAuthentication instanceof Saml2ModuleAuthentication){ + if (moduleAuthentication instanceof Saml2ModuleAuthentication) { providers = ((Saml2ModuleAuthentication) moduleAuthentication).getProviders(); - if (!providers.isEmpty() && providers.size() == 1 + if (providers.size() == 1 && request.getSession().getAttribute("SPRING_SECURITY_LAST_EXCEPTION") == null) { response.sendRedirect(providers.get(0).getRedirectLink()); return; diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/util/SecurityUtils.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/util/SecurityUtils.java index b1a023112ce..30a9105556a 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/util/SecurityUtils.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/util/SecurityUtils.java @@ -1,625 +1,623 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.web.security.util; - -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.model.api.ModelInteractionService; -import com.evolveum.midpoint.model.api.ModelService; -import com.evolveum.midpoint.model.api.authentication.*; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.schema.SearchResultList; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.util.SecurityPolicyUtil; -import com.evolveum.midpoint.security.api.AuthorizationConstants; -import com.evolveum.midpoint.security.api.SecurityContextManager; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.task.api.TaskManager; -import com.evolveum.midpoint.util.Producer; -import com.evolveum.midpoint.util.exception.*; -import com.evolveum.midpoint.util.logging.LoggingUtils; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.application.AuthorizationAction; -import com.evolveum.midpoint.web.application.DescriptorLoader; -import com.evolveum.midpoint.web.application.PageDescriptor; -import com.evolveum.midpoint.web.security.factory.channel.AbstractChannelFactory; -import com.evolveum.midpoint.web.security.factory.channel.AuthChannelRegistryImpl; -import com.evolveum.midpoint.web.security.factory.module.HttpClusterModuleFactory; -import com.evolveum.midpoint.web.security.module.authentication.HttpModuleAuthentication; -import com.evolveum.midpoint.web.security.module.configuration.ModuleWebSecurityConfigurationImpl; -import com.evolveum.midpoint.web.security.factory.module.AuthModuleRegistryImpl; -import com.evolveum.midpoint.web.security.factory.module.AbstractModuleFactory; -import com.evolveum.midpoint.web.component.menu.MainMenuItem; -import com.evolveum.midpoint.web.component.menu.MenuItem; - -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import com.github.openjson.JSONArray; -import com.github.openjson.JSONObject; -import org.apache.commons.lang3.Validate; -import org.apache.wicket.markup.ComponentTag; -import org.apache.wicket.markup.MarkupStream; -import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.request.Request; -import org.apache.wicket.request.Response; -import org.apache.wicket.request.cycle.RequestCycle; -import org.jetbrains.annotations.NotNull; -import org.springframework.security.authentication.AuthenticationServiceException; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.web.WebAttributes; -import org.springframework.security.web.csrf.CsrfToken; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; -import org.springframework.web.context.ContextLoader; -import org.springframework.web.context.WebApplicationContext; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; -import java.util.*; - -import static org.springframework.security.saml.util.StringUtils.stripSlashes; -import static org.springframework.security.saml.util.StringUtils.stripStartingSlashes; - -/** - * @author lazyman - * @author lskublik - */ -public class SecurityUtils { - - private static final Trace LOGGER = TraceManager.getTrace(SecurityUtils.class); - private static final String PROXY_USER_OID_HEADER = "Switch-To-Principal"; - public static final String DEFAULT_LOGOUT_PATH = "/logout"; - - public static GuiProfiledPrincipal getPrincipalUser() { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - - return getPrincipalUser(authentication); - } - - private static final Map LOCAL_PATH_AND_CHANNEL; - static { - Map map = new HashMap(); - map.put("ws/rest", SchemaConstants.CHANNEL_REST_URI); - map.put("actuator", SchemaConstants.CHANNEL_ACTUATOR_URI); - map.put("resetPassword", SchemaConstants.CHANNEL_GUI_RESET_PASSWORD_URI); - map.put("registration", SchemaConstants.CHANNEL_GUI_SELF_REGISTRATION_URI); - LOCAL_PATH_AND_CHANNEL = Collections.unmodifiableMap(map); - } - - public static GuiProfiledPrincipal getPrincipalUser(Authentication authentication) { - if (authentication == null) { - LOGGER.trace("Authentication not available in security context."); - return null; - } - - Object principal = authentication.getPrincipal(); - if (principal == null) { - return null; - } - if (principal instanceof GuiProfiledPrincipal) { - return (GuiProfiledPrincipal) principal; - } - if (AuthorizationConstants.ANONYMOUS_USER_PRINCIPAL.equals(principal)) { - // silently ignore to avoid filling the logs - return null; - } - LOGGER.debug("Principal user in security context holder is {} ({}) but not type of {}", - principal, principal.getClass(), GuiProfiledPrincipal.class.getName()); - return null; - } - - public static boolean isMenuAuthorized(MainMenuItem item) { - Class clazz = item.getPageClass(); - return clazz == null || isPageAuthorized(clazz); - } - - public static boolean isMenuAuthorized(MenuItem item) { - Class clazz = item.getPageClass(); - return isPageAuthorized(clazz); - } - - public static boolean isPageAuthorized(Class page) { - if (page == null) { - return false; - } - - PageDescriptor descriptor = (PageDescriptor) page.getAnnotation(PageDescriptor.class); - if (descriptor == null ){ - return false; - } - - - AuthorizationAction[] actions = descriptor.action(); - List list = new ArrayList<>(); - if (actions != null) { - for (AuthorizationAction action : actions) { - list.add(action.actionUri()); - } - } - - return WebComponentUtil.isAuthorized(list.toArray(new String[list.size()])); - } - - public static WebMarkupContainer createHiddenInputForCsrf(String id) { - WebMarkupContainer field = new WebMarkupContainer(id) { - - @Override - public void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) { - super.onComponentTagBody(markupStream, openTag); - - appendHiddenInputForCsrf(getResponse()); - } - }; - field.setRenderBodyOnly(true); - - return field; - } - - public static void appendHiddenInputForCsrf(Response resp) { - CsrfToken csrfToken = getCsrfToken(); - if (csrfToken == null) { - return; - } - - String parameterName = csrfToken.getParameterName(); - String value = csrfToken.getToken(); - - resp.write(""); - } - - public static CsrfToken getCsrfToken() { - Request req = RequestCycle.get().getRequest(); - HttpServletRequest httpReq = (HttpServletRequest) req.getContainerRequest(); - - return (CsrfToken) httpReq.getAttribute("_csrf"); - } - - public static AuthenticationSequenceType getSequenceByPath(HttpServletRequest httpRequest, AuthenticationsPolicyType authenticationPolicy){ - String localePath = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length()); - if (authenticationPolicy == null || authenticationPolicy.getSequence() == null - || authenticationPolicy.getSequence().isEmpty()) { - return null; - } - String[] partsOfLocalPath = stripStartingSlashes(localePath).split("/"); - - AuthenticationSequenceType specificSequence = getSpecificSequence(httpRequest); - if (specificSequence != null) { - return specificSequence; - } - - if (partsOfLocalPath.length >= 2 && partsOfLocalPath[0].equals(ModuleWebSecurityConfigurationImpl.DEFAULT_PREFIX_OF_MODULE)) { - AuthenticationSequenceType sequence = searchSequence(partsOfLocalPath[1], false, authenticationPolicy); - if (sequence == null) { - LOGGER.debug("Couldn't find sequence by preffix {}, so try default channel", partsOfLocalPath[1]); - sequence = searchSequence(SecurityPolicyUtil.DEFAULT_CHANNEL, true, authenticationPolicy); - } - return sequence; - } - String usedChannel = searchChannelByPath(localePath); - - if (usedChannel == null) { - usedChannel = SecurityPolicyUtil.DEFAULT_CHANNEL; - } - - AuthenticationSequenceType sequence = searchSequence(usedChannel, true, authenticationPolicy); - return sequence; - - } - - public static String searchChannelByPath(String localePath) { - for (String prefix : LOCAL_PATH_AND_CHANNEL.keySet()) { - if (stripStartingSlashes(localePath).startsWith(prefix)) { - return LOCAL_PATH_AND_CHANNEL.get(prefix); - } - } - return null; - } - - public static String searchPathByChannel(String searchchannel) { - for (Map.Entry entry : LOCAL_PATH_AND_CHANNEL.entrySet()) { - if (entry.getValue().equals(searchchannel)) { - return entry.getKey(); - } - } - return null; - } - - public static String findChannelByRequest(HttpServletRequest httpRequest) { - String localePath = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length()); - return searchChannelByPath(localePath); - } - - private static AuthenticationSequenceType getSpecificSequence(HttpServletRequest httpRequest) { - String localePath = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length()); - String channel = searchChannelByPath(localePath); - if (LOCAL_PATH_AND_CHANNEL.get("ws/rest").equals(channel)) { - String header = httpRequest.getHeader("Authorization"); - if (header != null) { - String type = header.split(" ")[0]; - if (NameOfModuleType.CLUSTER.getName().toLowerCase().equals(type.toLowerCase())) { - AuthenticationSequenceType sequence = new AuthenticationSequenceType(); - sequence.setName(NameOfModuleType.CLUSTER.getName()); - AuthenticationSequenceChannelType seqChannel = new AuthenticationSequenceChannelType(); - seqChannel.setUrlSuffix(NameOfModuleType.CLUSTER.getName().toLowerCase()); - return sequence; - } - } - } - return null; - } - - private static AuthenticationSequenceType searchSequence(String comparisonAttribute, boolean useOnlyChannel, AuthenticationsPolicyType authenticationPolicy) { - Validate.notBlank(comparisonAttribute, "Comparison attribute for searching of sequence is blank"); - for (AuthenticationSequenceType sequence : authenticationPolicy.getSequence()) { - if (sequence != null && sequence.getChannel() != null) { - if (useOnlyChannel && comparisonAttribute.equals(sequence.getChannel().getChannelId()) - && Boolean.TRUE.equals(sequence.getChannel().isDefault())) { - if (sequence.getModule() == null || sequence.getModule().isEmpty()){ - return null; - } - return sequence; - } else if (!useOnlyChannel && comparisonAttribute.equals(sequence.getChannel().getUrlSuffix())) { - if (sequence.getModule() == null || sequence.getModule().isEmpty()){ - return null; - } - return sequence; - } - } - } - return null; - } - - public static AuthenticationSequenceType getSequenceByName(String name, AuthenticationsPolicyType authenticationPolicy){ - if (authenticationPolicy == null || authenticationPolicy.getSequence() == null - || authenticationPolicy.getSequence().isEmpty()) { - return null; - } - - Validate.notBlank(name,"Name for searching of sequence is blank"); - for (AuthenticationSequenceType sequence : authenticationPolicy.getSequence()) { - if (sequence != null) { - if (name.equals(sequence.getName())) { - if (sequence.getModule() == null || sequence.getModule().isEmpty()){ - return null; - } - return sequence; - } - } - } - return null; - } - - public static List buildModuleFilters(AuthModuleRegistryImpl authRegistry, AuthenticationSequenceType sequence, - HttpServletRequest request, AuthenticationModulesType authenticationModulesType, - CredentialsPolicyType credentialPolicy, Map, Object> sharedObjects, - AuthenticationChannel authenticationChannel) { - Validate.notNull(authRegistry, "Registry for module factories is null"); - Validate.notEmpty(sequence.getModule(), "Sequence " + sequence.getName() + " don't contains authentication modules"); - - List specificModules = getSpecificModuleFilter(sequence.getChannel().getUrlSuffix(), request, - sharedObjects, authenticationModulesType, credentialPolicy); - if (specificModules != null) { - return specificModules; - } - - List sequenceModules = SecurityPolicyUtil.getSortedModules(sequence); - List authModules = new ArrayList(); - sequenceModules.forEach(sequenceModule -> { - try { - AbstractAuthenticationModuleType module = getModuleByName(sequenceModule.getName(), authenticationModulesType); - AbstractModuleFactory moduleFactory = authRegistry.findModelFactory(module); - AuthModule authModule = moduleFactory.createModuleFilter(module, sequence.getChannel().getUrlSuffix(), request, - sharedObjects, authenticationModulesType, credentialPolicy, authenticationChannel); - authModules.add(authModule); - } catch (Exception e) { - LOGGER.error("Couldn't build filter for module moduleFactory", e); - } - }); - if (authModules.isEmpty()) { - return null; - } - return authModules; - } - - private static List getSpecificModuleFilter(String urlSuffix, HttpServletRequest httpRequest, Map, Object> sharedObjects, - AuthenticationModulesType authenticationModulesType, CredentialsPolicyType credentialPolicy) { - String localePath = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length()); - String channel = searchChannelByPath(localePath); - if (LOCAL_PATH_AND_CHANNEL.get("ws/rest").equals(channel)) { - String header = httpRequest.getHeader("Authorization"); - if (header != null) { - String type = header.split(" ")[0]; - if (NameOfModuleType.CLUSTER.getName().toLowerCase().equals(type.toLowerCase())) { - List authModules = new ArrayList(); - WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext(); - HttpClusterModuleFactory factory = context.getBean(HttpClusterModuleFactory.class); - AbstractAuthenticationModuleType module = new AbstractAuthenticationModuleType() { - }; - module.setName(NameOfModuleType.CLUSTER.getName().toLowerCase() + "-module"); - try { - authModules.add(factory.createModuleFilter(module, urlSuffix, httpRequest, - sharedObjects, authenticationModulesType, credentialPolicy, null)); - } catch (Exception e) { - LOGGER.error("Couldn't create module for cluster authentication"); - return null; - } - return authModules; - } - } - } - return null; - } - - private static AbstractAuthenticationModuleType getModuleByName(String name, AuthenticationModulesType authenticationModulesType){ - List modules = new ArrayList(); - modules.addAll(authenticationModulesType.getLoginForm()); - modules.addAll(authenticationModulesType.getSaml2()); - modules.addAll(authenticationModulesType.getHttpBasic()); - modules.addAll(authenticationModulesType.getHttpHeader()); - modules.addAll(authenticationModulesType.getHttpSecQ()); - modules.addAll(authenticationModulesType.getMailNonce()); - modules.addAll(authenticationModulesType.getOidc()); - modules.addAll(authenticationModulesType.getSecurityQuestionsForm()); - modules.addAll(authenticationModulesType.getSmsNonce()); - modules.addAll(authenticationModulesType.getLdap()); - - for (AbstractAuthenticationModuleType module: modules) { - if (module.getName().equals(name)) { - return module; - } - } - return null; - } - - public static AbstractModuleFactory getFactoryByName(AuthModuleRegistryImpl authRegistry, String name, AuthenticationModulesType authenticationModulesType){ - AbstractAuthenticationModuleType module = getModuleByName(name, authenticationModulesType); - if (module != null) { - return authRegistry.findModelFactory(module); - } - return null; - } - - public static boolean isPermitAll(HttpServletRequest request) { - for (String url: DescriptorLoader.getPermitAllUrls()) { - AntPathRequestMatcher matcher = new AntPathRequestMatcher(url); - if (matcher.matches(request)) { - return true; - } - } - String servletPath = request.getServletPath(); - if ("".equals(servletPath) || "/".equals(servletPath)) { - // Special case, this is in fact "magic" redirect to home page or login page. It handles autz in its own way. - return true; - } - return false; - } - - public static boolean isLoginPage(HttpServletRequest request) { - for (String url: DescriptorLoader.getLoginPages()) { - AntPathRequestMatcher matcher = new AntPathRequestMatcher(url); - if (matcher.matches(request)) { - return true; - } - } - return false; - } - - public static ModuleAuthentication getProcessingModule(boolean required) { - Authentication actualAuthentication = SecurityContextHolder.getContext().getAuthentication(); - - if (actualAuthentication instanceof MidpointAuthentication) { - MidpointAuthentication mpAuthentication = (MidpointAuthentication) actualAuthentication; - ModuleAuthentication moduleAuthentication = mpAuthentication.getProcessingModuleAuthentication(); - if (required && moduleAuthentication == null) { - LOGGER.error("Couldn't find processing module authentication {}", mpAuthentication); - throw new AuthenticationServiceException("web.security.flexAuth.module.null"); - } - return moduleAuthentication; - } else if (required) { - LOGGER.error("Type of actual authentication in security context isn't MidpointAuthentication"); - throw new AuthenticationServiceException("web.security.flexAuth.auth.wrong.type"); - } - return null; - } - - public static void saveException(HttpServletRequest request, - AuthenticationException exception) { - HttpSession session = request.getSession(false); - - request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception); - } - - public static AuthenticationChannel buildAuthChannel(AuthChannelRegistryImpl registry, AuthenticationSequenceType sequence) { - Validate.notNull(sequence, "Couldn't build authentication channel object, because sequence is null"); - String channelId = null; - AuthenticationSequenceChannelType channelSequence = sequence.getChannel(); - if (channelSequence != null) { - channelId = channelSequence.getChannelId(); - } - - AbstractChannelFactory factory = registry.findModelFactory(channelId); - if (factory == null) { - LOGGER.error("Couldn't find factory for {}", channelId); - return null; - } - AuthenticationChannel channel = null; - try { - channel = factory.createAuthChannel(channelSequence); - } catch (Exception e) { - LOGGER.error("Couldn't create channel for {}", channelId); - } - return channel; - } - -// public static ModuleAuthentication createDefaultAuthenticationModule() { -// LoginFormModuleAuthentication moduleAuthentication = new LoginFormModuleAuthentication(); -// moduleAuthentication.setPrefix(ModuleWebSecurityConfigurationImpl.DEFAULT_PREFIX_OF_MODULE_WITH_SLASH -// + ModuleWebSecurityConfigurationImpl.DEFAULT_PREFIX_FOR_DEFAULT_MODULE + SecurityPolicyUtil.DEFAULT_MODULE_NAME + "/"); -// moduleAuthentication.setNameOfModule(SecurityPolicyUtil.DEFAULT_MODULE_NAME); -// return moduleAuthentication; -// } - - public static Map obtainAnswers(String answers, String idParameter, String answerParameter) { - if (answers == null) { - return null; - } - - JSONArray answersList = new JSONArray(answers); - Map questionAnswers = new HashMap(); - for (int i = 0; i < answersList.length(); i++) { - JSONObject answer = answersList.getJSONObject(i); - String questionId = answer.getString(idParameter); - String questionAnswer = answer.getString(answerParameter); - questionAnswers.put(questionId, questionAnswer); - } - return questionAnswers; - } - - public static void resolveProxyUserOidHeader(HttpServletRequest request) { - String proxyUserOid = request.getHeader(PROXY_USER_OID_HEADER); - - Authentication actualAuth = SecurityContextHolder.getContext().getAuthentication(); - - if (proxyUserOid != null && actualAuth instanceof MidpointAuthentication) { - ModuleAuthentication moduleAuth = ((MidpointAuthentication) actualAuth).getProcessingModuleAuthentication(); - if (moduleAuth != null && moduleAuth instanceof HttpModuleAuthentication) { - ((HttpModuleAuthentication) moduleAuth).setProxyUserOid(proxyUserOid); - } - } - } - - private static Task createAnonymousTask(String operation, TaskManager manager) { - Task task = manager.createTaskInstance(operation); - task.setChannel(SchemaConstants.CHANNEL_GUI_USER_URI); - return task; - } - - public static UserType searchUserPrivileged(String username, SecurityContextManager securityContextManager, TaskManager manager, - ModelService modelService, PrismContext prismContext) { - UserType userType = securityContextManager.runPrivileged(new Producer() { - ObjectQuery query = prismContext.queryFor(UserType.class).item(UserType.F_NAME) - .eqPoly(username).matchingNorm().build(); - - @Override - public UserType run() { - - Task task = createAnonymousTask("load user", manager); - OperationResult result = new OperationResult("search user"); - - SearchResultList> users; - try { - users = modelService.searchObjects(UserType.class, query, null, task, result); - } catch (SchemaException | ObjectNotFoundException | SecurityViolationException - | CommunicationException | ConfigurationException | ExpressionEvaluationException e) { - LoggingUtils.logException(LOGGER, "failed to search user", e); - return null; - } - - if ((users == null) || (users.isEmpty())) { - LOGGER.trace("Empty user list in ForgetPassword"); - return null; - } - - if (users.size() > 1) { - LOGGER.trace("Problem while seeking for user"); - return null; - } - - UserType user = users.iterator().next().asObjectable(); - LOGGER.trace("User found for ForgetPassword: {}", user); - - return user; - } - - }); - return userType; - } - - public static SecurityPolicyType resolveSecurityPolicy(PrismObject user, SecurityContextManager securityContextManager, TaskManager manager, - ModelInteractionService modelInteractionService) { - SecurityPolicyType securityPolicy = securityContextManager.runPrivileged(new Producer() { - private static final long serialVersionUID = 1L; - - @Override - public SecurityPolicyType run() { - - Task task = createAnonymousTask("get security policy", manager); - OperationResult result = new OperationResult("get security policy"); - - try { - return modelInteractionService.getSecurityPolicy(user, task, result); - } catch (CommonException e) { - LOGGER.error("Could not retrieve security policy: {}", e.getMessage(), e); - return null; - } - - } - - }); - - return securityPolicy; - } - - public static boolean isIgnoredLocalPath(AuthenticationsPolicyType authenticationsPolicy, HttpServletRequest httpRequest) { - if (authenticationsPolicy != null && authenticationsPolicy.getIgnoredLocalPath() != null - && !authenticationsPolicy.getIgnoredLocalPath().isEmpty()) { - List ignoredPaths = authenticationsPolicy.getIgnoredLocalPath(); - for (String ignoredPath : ignoredPaths) { - AntPathRequestMatcher matcher = new AntPathRequestMatcher(ignoredPath); - if (matcher.matches(httpRequest)) { - return true; - } - } - } - return false; - } - - public static String getPathForLogoutWithContextPath(String contextPath, @NotNull ModuleAuthentication moduleAuthentication) { - return "/" + stripSlashes(contextPath) + getPathForLogout(moduleAuthentication); - } - - public static String getPathForLogout(@NotNull ModuleAuthentication moduleAuthentication) { - return "/" + stripSlashes(moduleAuthentication.getPrefix()) + DEFAULT_LOGOUT_PATH; - } - - public static ModuleAuthentication getAuthenticatedModule() { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - - if (authentication instanceof MidpointAuthentication) { - MidpointAuthentication mpAuthentication = (MidpointAuthentication) authentication; - for (ModuleAuthentication moduleAuthentication : mpAuthentication.getAuthentications()) { - if (StateOfModule.SUCCESSFULLY.equals(moduleAuthentication.getState())) { - return moduleAuthentication; - } - } - } else { - String message = "Unsupported type " + (authentication == null ? null : authentication.getClass().getName()) - + " of authentication for MidpointLogoutRedirectFilter, supported is only MidpointAuthentication"; - throw new IllegalArgumentException(message); - } - return null; - } - - public static boolean isBasePathForSequence(HttpServletRequest httpRequest, AuthenticationSequenceType sequence) { - String localePath = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length()); - if (!localePath.startsWith(ModuleWebSecurityConfigurationImpl.DEFAULT_PREFIX_OF_MODULE_WITH_SLASH)) { - return false; - } - String defaultPrefix = ModuleWebSecurityConfigurationImpl.DEFAULT_PREFIX_OF_MODULE_WITH_SLASH; - int startIndex = localePath.indexOf(defaultPrefix) + defaultPrefix.length(); - localePath = localePath.substring(startIndex); - if (sequence == null || sequence.getChannel() == null || sequence.getChannel().getUrlSuffix() == null - || !stripSlashes(localePath).equals(stripSlashes(sequence.getChannel().getUrlSuffix()))) { - return false; - } - return true; - } -} +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.web.security.util; + +import static org.springframework.security.saml.util.StringUtils.stripSlashes; +import static org.springframework.security.saml.util.StringUtils.stripStartingSlashes; + +import java.util.*; +import javax.servlet.http.HttpServletRequest; + +import com.github.openjson.JSONArray; +import com.github.openjson.JSONObject; +import org.apache.commons.lang3.Validate; +import org.apache.wicket.markup.ComponentTag; +import org.apache.wicket.markup.MarkupStream; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.request.Request; +import org.apache.wicket.request.Response; +import org.apache.wicket.request.cycle.RequestCycle; +import org.jetbrains.annotations.NotNull; +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.WebAttributes; +import org.springframework.security.web.csrf.CsrfToken; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.web.context.ContextLoader; +import org.springframework.web.context.WebApplicationContext; + +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.model.api.ModelInteractionService; +import com.evolveum.midpoint.model.api.ModelService; +import com.evolveum.midpoint.model.api.authentication.*; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.schema.SearchResultList; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.SecurityPolicyUtil; +import com.evolveum.midpoint.security.api.AuthorizationConstants; +import com.evolveum.midpoint.security.api.SecurityContextManager; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.task.api.TaskManager; +import com.evolveum.midpoint.util.Producer; +import com.evolveum.midpoint.util.exception.*; +import com.evolveum.midpoint.util.logging.LoggingUtils; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.application.AuthorizationAction; +import com.evolveum.midpoint.web.application.DescriptorLoader; +import com.evolveum.midpoint.web.application.PageDescriptor; +import com.evolveum.midpoint.web.component.menu.MainMenuItem; +import com.evolveum.midpoint.web.component.menu.MenuItem; +import com.evolveum.midpoint.web.security.factory.channel.AbstractChannelFactory; +import com.evolveum.midpoint.web.security.factory.channel.AuthChannelRegistryImpl; +import com.evolveum.midpoint.web.security.factory.module.AbstractModuleFactory; +import com.evolveum.midpoint.web.security.factory.module.AuthModuleRegistryImpl; +import com.evolveum.midpoint.web.security.factory.module.HttpClusterModuleFactory; +import com.evolveum.midpoint.web.security.module.authentication.HttpModuleAuthentication; +import com.evolveum.midpoint.web.security.module.configuration.ModuleWebSecurityConfigurationImpl; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; + +/** + * @author lazyman + * @author lskublik + */ +public class SecurityUtils { + + private static final Trace LOGGER = TraceManager.getTrace(SecurityUtils.class); + private static final String PROXY_USER_OID_HEADER = "Switch-To-Principal"; + public static final String DEFAULT_LOGOUT_PATH = "/logout"; + + public static GuiProfiledPrincipal getPrincipalUser() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + return getPrincipalUser(authentication); + } + + private static final Map LOCAL_PATH_AND_CHANNEL; + + static { + Map map = new HashMap<>(); + map.put("ws/rest", SchemaConstants.CHANNEL_REST_URI); + map.put("rest2", SchemaConstants.CHANNEL_REST_URI); + map.put("actuator", SchemaConstants.CHANNEL_ACTUATOR_URI); + map.put("resetPassword", SchemaConstants.CHANNEL_GUI_RESET_PASSWORD_URI); + map.put("registration", SchemaConstants.CHANNEL_GUI_SELF_REGISTRATION_URI); + LOCAL_PATH_AND_CHANNEL = Collections.unmodifiableMap(map); + } + + public static GuiProfiledPrincipal getPrincipalUser(Authentication authentication) { + if (authentication == null) { + LOGGER.trace("Authentication not available in security context."); + return null; + } + + Object principal = authentication.getPrincipal(); + if (principal == null) { + return null; + } + if (principal instanceof GuiProfiledPrincipal) { + return (GuiProfiledPrincipal) principal; + } + if (AuthorizationConstants.ANONYMOUS_USER_PRINCIPAL.equals(principal)) { + // silently ignore to avoid filling the logs + return null; + } + LOGGER.debug("Principal user in security context holder is {} ({}) but not type of {}", + principal, principal.getClass(), GuiProfiledPrincipal.class.getName()); + return null; + } + + public static boolean isMenuAuthorized(MainMenuItem item) { + Class clazz = item.getPageClass(); + return clazz == null || isPageAuthorized(clazz); + } + + public static boolean isMenuAuthorized(MenuItem item) { + Class clazz = item.getPageClass(); + return isPageAuthorized(clazz); + } + + public static boolean isPageAuthorized(Class page) { + if (page == null) { + return false; + } + + PageDescriptor descriptor = (PageDescriptor) page.getAnnotation(PageDescriptor.class); + if (descriptor == null) { + return false; + } + + AuthorizationAction[] actions = descriptor.action(); + List list = new ArrayList<>(); + if (actions != null) { + for (AuthorizationAction action : actions) { + list.add(action.actionUri()); + } + } + + return WebComponentUtil.isAuthorized(list.toArray(new String[list.size()])); + } + + public static WebMarkupContainer createHiddenInputForCsrf(String id) { + WebMarkupContainer field = new WebMarkupContainer(id) { + + @Override + public void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) { + super.onComponentTagBody(markupStream, openTag); + + appendHiddenInputForCsrf(getResponse()); + } + }; + field.setRenderBodyOnly(true); + + return field; + } + + public static void appendHiddenInputForCsrf(Response resp) { + CsrfToken csrfToken = getCsrfToken(); + if (csrfToken == null) { + return; + } + + String parameterName = csrfToken.getParameterName(); + String value = csrfToken.getToken(); + + resp.write(""); + } + + public static CsrfToken getCsrfToken() { + Request req = RequestCycle.get().getRequest(); + HttpServletRequest httpReq = (HttpServletRequest) req.getContainerRequest(); + + return (CsrfToken) httpReq.getAttribute("_csrf"); + } + + public static AuthenticationSequenceType getSequenceByPath(HttpServletRequest httpRequest, AuthenticationsPolicyType authenticationPolicy) { + String localePath = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length()); + if (authenticationPolicy == null || authenticationPolicy.getSequence() == null + || authenticationPolicy.getSequence().isEmpty()) { + return null; + } + String[] partsOfLocalPath = stripStartingSlashes(localePath).split("/"); + + AuthenticationSequenceType specificSequence = getSpecificSequence(httpRequest); + if (specificSequence != null) { + return specificSequence; + } + + if (partsOfLocalPath.length >= 2 && partsOfLocalPath[0].equals(ModuleWebSecurityConfigurationImpl.DEFAULT_PREFIX_OF_MODULE)) { + AuthenticationSequenceType sequence = searchSequence(partsOfLocalPath[1], false, authenticationPolicy); + if (sequence == null) { + LOGGER.debug("Couldn't find sequence by preffix {}, so try default channel", partsOfLocalPath[1]); + sequence = searchSequence(SecurityPolicyUtil.DEFAULT_CHANNEL, true, authenticationPolicy); + } + return sequence; + } + String usedChannel = searchChannelByPath(localePath); + + if (usedChannel == null) { + usedChannel = SecurityPolicyUtil.DEFAULT_CHANNEL; + } + + AuthenticationSequenceType sequence = searchSequence(usedChannel, true, authenticationPolicy); + return sequence; + + } + + public static String searchChannelByPath(String localePath) { + for (String prefix : LOCAL_PATH_AND_CHANNEL.keySet()) { + if (stripStartingSlashes(localePath).startsWith(prefix)) { + return LOCAL_PATH_AND_CHANNEL.get(prefix); + } + } + return null; + } + + public static String searchPathByChannel(String searchchannel) { + for (Map.Entry entry : LOCAL_PATH_AND_CHANNEL.entrySet()) { + if (entry.getValue().equals(searchchannel)) { + return entry.getKey(); + } + } + return null; + } + + public static String findChannelByRequest(HttpServletRequest httpRequest) { + String localePath = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length()); + return searchChannelByPath(localePath); + } + + private static AuthenticationSequenceType getSpecificSequence(HttpServletRequest httpRequest) { + String localePath = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length()); + String channel = searchChannelByPath(localePath); + if (LOCAL_PATH_AND_CHANNEL.get("ws/rest").equals(channel)) { + String header = httpRequest.getHeader("Authorization"); + if (header != null) { + String type = header.split(" ")[0]; + if (NameOfModuleType.CLUSTER.getName().toLowerCase().equals(type.toLowerCase())) { + AuthenticationSequenceType sequence = new AuthenticationSequenceType(); + sequence.setName(NameOfModuleType.CLUSTER.getName()); + AuthenticationSequenceChannelType seqChannel = new AuthenticationSequenceChannelType(); + seqChannel.setUrlSuffix(NameOfModuleType.CLUSTER.getName().toLowerCase()); + return sequence; + } + } + } + return null; + } + + private static AuthenticationSequenceType searchSequence(String comparisonAttribute, boolean useOnlyChannel, AuthenticationsPolicyType authenticationPolicy) { + Validate.notBlank(comparisonAttribute, "Comparison attribute for searching of sequence is blank"); + for (AuthenticationSequenceType sequence : authenticationPolicy.getSequence()) { + if (sequence != null && sequence.getChannel() != null) { + if (useOnlyChannel && comparisonAttribute.equals(sequence.getChannel().getChannelId()) + && Boolean.TRUE.equals(sequence.getChannel().isDefault())) { + if (sequence.getModule() == null || sequence.getModule().isEmpty()) { + return null; + } + return sequence; + } else if (!useOnlyChannel && comparisonAttribute.equals(sequence.getChannel().getUrlSuffix())) { + if (sequence.getModule() == null || sequence.getModule().isEmpty()) { + return null; + } + return sequence; + } + } + } + return null; + } + + public static AuthenticationSequenceType getSequenceByName(String name, AuthenticationsPolicyType authenticationPolicy) { + if (authenticationPolicy == null || authenticationPolicy.getSequence() == null + || authenticationPolicy.getSequence().isEmpty()) { + return null; + } + + Validate.notBlank(name, "Name for searching of sequence is blank"); + for (AuthenticationSequenceType sequence : authenticationPolicy.getSequence()) { + if (sequence != null) { + if (name.equals(sequence.getName())) { + if (sequence.getModule() == null || sequence.getModule().isEmpty()) { + return null; + } + return sequence; + } + } + } + return null; + } + + public static List buildModuleFilters(AuthModuleRegistryImpl authRegistry, AuthenticationSequenceType sequence, + HttpServletRequest request, AuthenticationModulesType authenticationModulesType, + CredentialsPolicyType credentialPolicy, Map, Object> sharedObjects, + AuthenticationChannel authenticationChannel) { + Validate.notNull(authRegistry, "Registry for module factories is null"); + Validate.notEmpty(sequence.getModule(), "Sequence " + sequence.getName() + " don't contains authentication modules"); + + List specificModules = getSpecificModuleFilter(sequence.getChannel().getUrlSuffix(), request, + sharedObjects, authenticationModulesType, credentialPolicy); + if (specificModules != null) { + return specificModules; + } + + List sequenceModules = SecurityPolicyUtil.getSortedModules(sequence); + List authModules = new ArrayList<>(); + sequenceModules.forEach(sequenceModule -> { + try { + AbstractAuthenticationModuleType module = getModuleByName(sequenceModule.getName(), authenticationModulesType); + AbstractModuleFactory moduleFactory = authRegistry.findModelFactory(module); + AuthModule authModule = moduleFactory.createModuleFilter(module, sequence.getChannel().getUrlSuffix(), request, + sharedObjects, authenticationModulesType, credentialPolicy, authenticationChannel); + authModules.add(authModule); + } catch (Exception e) { + LOGGER.error("Couldn't build filter for module moduleFactory", e); + } + }); + if (authModules.isEmpty()) { + return null; + } + return authModules; + } + + private static List getSpecificModuleFilter(String urlSuffix, HttpServletRequest httpRequest, Map, Object> sharedObjects, + AuthenticationModulesType authenticationModulesType, CredentialsPolicyType credentialPolicy) { + String localePath = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length()); + String channel = searchChannelByPath(localePath); + if (LOCAL_PATH_AND_CHANNEL.get("ws/rest").equals(channel)) { + String header = httpRequest.getHeader("Authorization"); + if (header != null) { + String type = header.split(" ")[0]; + if (NameOfModuleType.CLUSTER.getName().toLowerCase().equals(type.toLowerCase())) { + List authModules = new ArrayList<>(); + WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext(); + HttpClusterModuleFactory factory = context.getBean(HttpClusterModuleFactory.class); + AbstractAuthenticationModuleType module = new AbstractAuthenticationModuleType() { + }; + module.setName(NameOfModuleType.CLUSTER.getName().toLowerCase() + "-module"); + try { + authModules.add(factory.createModuleFilter(module, urlSuffix, httpRequest, + sharedObjects, authenticationModulesType, credentialPolicy, null)); + } catch (Exception e) { + LOGGER.error("Couldn't create module for cluster authentication"); + return null; + } + return authModules; + } + } + } + return null; + } + + private static AbstractAuthenticationModuleType getModuleByName(String name, AuthenticationModulesType authenticationModulesType) { + List modules = new ArrayList<>(); + modules.addAll(authenticationModulesType.getLoginForm()); + modules.addAll(authenticationModulesType.getSaml2()); + modules.addAll(authenticationModulesType.getHttpBasic()); + modules.addAll(authenticationModulesType.getHttpHeader()); + modules.addAll(authenticationModulesType.getHttpSecQ()); + modules.addAll(authenticationModulesType.getMailNonce()); + modules.addAll(authenticationModulesType.getOidc()); + modules.addAll(authenticationModulesType.getSecurityQuestionsForm()); + modules.addAll(authenticationModulesType.getSmsNonce()); + modules.addAll(authenticationModulesType.getLdap()); + + for (AbstractAuthenticationModuleType module : modules) { + if (module.getName().equals(name)) { + return module; + } + } + return null; + } + + public static AbstractModuleFactory getFactoryByName(AuthModuleRegistryImpl authRegistry, String name, AuthenticationModulesType authenticationModulesType) { + AbstractAuthenticationModuleType module = getModuleByName(name, authenticationModulesType); + if (module != null) { + return authRegistry.findModelFactory(module); + } + return null; + } + + public static boolean isPermitAll(HttpServletRequest request) { + for (String url : DescriptorLoader.getPermitAllUrls()) { + AntPathRequestMatcher matcher = new AntPathRequestMatcher(url); + if (matcher.matches(request)) { + return true; + } + } + String servletPath = request.getServletPath(); + if ("".equals(servletPath) || "/".equals(servletPath)) { + // Special case, this is in fact "magic" redirect to home page or login page. It handles autz in its own way. + return true; + } + return false; + } + + public static boolean isLoginPage(HttpServletRequest request) { + for (String url : DescriptorLoader.getLoginPages()) { + AntPathRequestMatcher matcher = new AntPathRequestMatcher(url); + if (matcher.matches(request)) { + return true; + } + } + return false; + } + + public static ModuleAuthentication getProcessingModule(boolean required) { + Authentication actualAuthentication = SecurityContextHolder.getContext().getAuthentication(); + + if (actualAuthentication instanceof MidpointAuthentication) { + MidpointAuthentication mpAuthentication = (MidpointAuthentication) actualAuthentication; + ModuleAuthentication moduleAuthentication = mpAuthentication.getProcessingModuleAuthentication(); + if (required && moduleAuthentication == null) { + LOGGER.error("Couldn't find processing module authentication {}", mpAuthentication); + throw new AuthenticationServiceException("web.security.flexAuth.module.null"); + } + return moduleAuthentication; + } else if (required) { + LOGGER.error("Type of actual authentication in security context isn't MidpointAuthentication"); + throw new AuthenticationServiceException("web.security.flexAuth.auth.wrong.type"); + } + return null; + } + + public static void saveException(HttpServletRequest request, + AuthenticationException exception) { + request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception); + } + + public static AuthenticationChannel buildAuthChannel(AuthChannelRegistryImpl registry, AuthenticationSequenceType sequence) { + Validate.notNull(sequence, "Couldn't build authentication channel object, because sequence is null"); + String channelId = null; + AuthenticationSequenceChannelType channelSequence = sequence.getChannel(); + if (channelSequence != null) { + channelId = channelSequence.getChannelId(); + } + + AbstractChannelFactory factory = registry.findModelFactory(channelId); + if (factory == null) { + LOGGER.error("Couldn't find factory for {}", channelId); + return null; + } + AuthenticationChannel channel = null; + try { + channel = factory.createAuthChannel(channelSequence); + } catch (Exception e) { + LOGGER.error("Couldn't create channel for {}", channelId); + } + return channel; + } + +// public static ModuleAuthentication createDefaultAuthenticationModule() { +// LoginFormModuleAuthentication moduleAuthentication = new LoginFormModuleAuthentication(); +// moduleAuthentication.setPrefix(ModuleWebSecurityConfigurationImpl.DEFAULT_PREFIX_OF_MODULE_WITH_SLASH +// + ModuleWebSecurityConfigurationImpl.DEFAULT_PREFIX_FOR_DEFAULT_MODULE + SecurityPolicyUtil.DEFAULT_MODULE_NAME + "/"); +// moduleAuthentication.setNameOfModule(SecurityPolicyUtil.DEFAULT_MODULE_NAME); +// return moduleAuthentication; +// } + + public static Map obtainAnswers(String answers, String idParameter, String answerParameter) { + if (answers == null) { + return null; + } + + JSONArray answersList = new JSONArray(answers); + Map questionAnswers = new HashMap<>(); + for (int i = 0; i < answersList.length(); i++) { + JSONObject answer = answersList.getJSONObject(i); + String questionId = answer.getString(idParameter); + String questionAnswer = answer.getString(answerParameter); + questionAnswers.put(questionId, questionAnswer); + } + return questionAnswers; + } + + public static void resolveProxyUserOidHeader(HttpServletRequest request) { + String proxyUserOid = request.getHeader(PROXY_USER_OID_HEADER); + + Authentication actualAuth = SecurityContextHolder.getContext().getAuthentication(); + + if (proxyUserOid != null && actualAuth instanceof MidpointAuthentication) { + ModuleAuthentication moduleAuth = ((MidpointAuthentication) actualAuth).getProcessingModuleAuthentication(); + if (moduleAuth instanceof HttpModuleAuthentication) { + ((HttpModuleAuthentication) moduleAuth).setProxyUserOid(proxyUserOid); + } + } + } + + private static Task createAnonymousTask(String operation, TaskManager manager) { + Task task = manager.createTaskInstance(operation); + task.setChannel(SchemaConstants.CHANNEL_GUI_USER_URI); + return task; + } + + public static UserType searchUserPrivileged(String username, SecurityContextManager securityContextManager, TaskManager manager, + ModelService modelService, PrismContext prismContext) { + UserType userType = securityContextManager.runPrivileged(new Producer() { + ObjectQuery query = prismContext.queryFor(UserType.class).item(UserType.F_NAME) + .eqPoly(username).matchingNorm().build(); + + @Override + public UserType run() { + + Task task = createAnonymousTask("load user", manager); + OperationResult result = new OperationResult("search user"); + + SearchResultList> users; + try { + users = modelService.searchObjects(UserType.class, query, null, task, result); + } catch (SchemaException | ObjectNotFoundException | SecurityViolationException + | CommunicationException | ConfigurationException | ExpressionEvaluationException e) { + LoggingUtils.logException(LOGGER, "failed to search user", e); + return null; + } + + if ((users == null) || (users.isEmpty())) { + LOGGER.trace("Empty user list in ForgetPassword"); + return null; + } + + if (users.size() > 1) { + LOGGER.trace("Problem while seeking for user"); + return null; + } + + UserType user = users.iterator().next().asObjectable(); + LOGGER.trace("User found for ForgetPassword: {}", user); + + return user; + } + + }); + return userType; + } + + public static SecurityPolicyType resolveSecurityPolicy(PrismObject user, SecurityContextManager securityContextManager, TaskManager manager, + ModelInteractionService modelInteractionService) { + SecurityPolicyType securityPolicy = securityContextManager.runPrivileged(new Producer() { + private static final long serialVersionUID = 1L; + + @Override + public SecurityPolicyType run() { + + Task task = createAnonymousTask("get security policy", manager); + OperationResult result = new OperationResult("get security policy"); + + try { + return modelInteractionService.getSecurityPolicy(user, task, result); + } catch (CommonException e) { + LOGGER.error("Could not retrieve security policy: {}", e.getMessage(), e); + return null; + } + + } + + }); + + return securityPolicy; + } + + public static boolean isIgnoredLocalPath(AuthenticationsPolicyType authenticationsPolicy, HttpServletRequest httpRequest) { + if (authenticationsPolicy != null && authenticationsPolicy.getIgnoredLocalPath() != null + && !authenticationsPolicy.getIgnoredLocalPath().isEmpty()) { + List ignoredPaths = authenticationsPolicy.getIgnoredLocalPath(); + for (String ignoredPath : ignoredPaths) { + AntPathRequestMatcher matcher = new AntPathRequestMatcher(ignoredPath); + if (matcher.matches(httpRequest)) { + return true; + } + } + } + return false; + } + + public static String getPathForLogoutWithContextPath(String contextPath, @NotNull ModuleAuthentication moduleAuthentication) { + return "/" + stripSlashes(contextPath) + getPathForLogout(moduleAuthentication); + } + + public static String getPathForLogout(@NotNull ModuleAuthentication moduleAuthentication) { + return "/" + stripSlashes(moduleAuthentication.getPrefix()) + DEFAULT_LOGOUT_PATH; + } + + public static ModuleAuthentication getAuthenticatedModule() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (authentication instanceof MidpointAuthentication) { + MidpointAuthentication mpAuthentication = (MidpointAuthentication) authentication; + for (ModuleAuthentication moduleAuthentication : mpAuthentication.getAuthentications()) { + if (StateOfModule.SUCCESSFULLY.equals(moduleAuthentication.getState())) { + return moduleAuthentication; + } + } + } else { + String message = "Unsupported type " + (authentication == null ? null : authentication.getClass().getName()) + + " of authentication for MidpointLogoutRedirectFilter, supported is only MidpointAuthentication"; + throw new IllegalArgumentException(message); + } + return null; + } + + public static boolean isBasePathForSequence(HttpServletRequest httpRequest, AuthenticationSequenceType sequence) { + String localePath = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length()); + if (!localePath.startsWith(ModuleWebSecurityConfigurationImpl.DEFAULT_PREFIX_OF_MODULE_WITH_SLASH)) { + return false; + } + String defaultPrefix = ModuleWebSecurityConfigurationImpl.DEFAULT_PREFIX_OF_MODULE_WITH_SLASH; + int startIndex = localePath.indexOf(defaultPrefix) + defaultPrefix.length(); + localePath = localePath.substring(startIndex); + if (sequence == null || sequence.getChannel() == null || sequence.getChannel().getUrlSuffix() == null + || !stripSlashes(localePath).equals(stripSlashes(sequence.getChannel().getUrlSuffix()))) { + return false; + } + return true; + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/SchrodingerComponentInitListener.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/SchrodingerComponentInitListener.java index bae4700c3e2..3334638e2fa 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/SchrodingerComponentInitListener.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/SchrodingerComponentInitListener.java @@ -11,8 +11,11 @@ import javax.xml.namespace.QName; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.impl.prism.*; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; + +import com.evolveum.midpoint.gui.impl.prism.panel.ItemPanel; +import com.evolveum.midpoint.gui.impl.prism.panel.PrismPropertyPanel; +import com.evolveum.midpoint.gui.impl.prism.panel.PrismReferencePanel; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.reflect.FieldUtils; diff --git a/gui/admin-gui/src/main/resources/application.yml b/gui/admin-gui/src/main/resources/application.yml index 7a22de92744..f7a3d06394e 100644 --- a/gui/admin-gui/src/main/resources/application.yml +++ b/gui/admin-gui/src/main/resources/application.yml @@ -15,7 +15,7 @@ spring: server: tomcat: basedir: ${midpoint.home} - max-http-post-size: 104857600 # in bytes + max-http-form-post-size: 100MB ## Enable and configuration ajp connector for mp # ajp: # enabled: true diff --git a/gui/admin-gui/src/main/resources/static/less/midpoint-theme.less b/gui/admin-gui/src/main/resources/static/less/midpoint-theme.less index c21bfff8e23..5147d5c65ec 100644 --- a/gui/admin-gui/src/main/resources/static/less/midpoint-theme.less +++ b/gui/admin-gui/src/main/resources/static/less/midpoint-theme.less @@ -845,35 +845,52 @@ body .treeview-menu > li > span:hover { } .top-level-prism-container { - border-top: 1px solid #ddd; - padding-top: 5px; -} - -.multivalue-container > .container-wrapper > div { - padding-left: 40px; -} - -//top-level-prism-container is class for first showed container -.top-level-prism-container > .container-wrapper > div > div > -.prism-properties > .prism-containers { - padding-left: 0px; //align one-level containers -} - -//top-level-prism-container is class for first showed container -.top-level-prism-container > .container-wrapper > div > div > -.prism-properties > .prism-containers > .prism-property { - border-top: 1px solid #ddd; // line over area of container -} + border-top: 1px solid @table-divider-color; + padding-top: 5px; -.prism-containers > .top-level-prism-container > .container-wrapper > div > div > .prism-properties > .prism-containers { - padding-left: 40px; -} -.prism-containers > .top-level-prism-container > .container-wrapper > div > div > .prism-properties > .prism-containers > .prism-property { - border-top: 0px solid #ddd; + .prism-properties { + .prism-container { + padding-left: 0px; + border-top: 1px solid @table-divider-color; + + .prism-container { + padding-left: 40px; + border-top: 0px solid @table-divider-color; + } + .prism-container.multivalue-container { + padding-left: 40px; + border-top: 0px solid @table-divider-color; + } + + } + + .prism-container.multivalue-container { + padding-left: 0px; + border-top: 1px solid @table-divider-color; + + .prism-container.multivalue-container { + padding-left: 40px; + border-top: 0px solid @table-divider-color; + + .container-wrapper { + padding-left: 40px; + border-top: 0px solid @table-divider-color; + } + } + + .container-wrapper { + padding-left: 40px; + border-top: 0px solid @table-divider-color; + + .container-wrapper { + padding-left: 0px; + border-top: 0px solid @table-divider-color; + } + } + } + } } - - .top-level-prism-container .row { margin-right: 0px; margin-left: 0px; @@ -885,12 +902,6 @@ body .treeview-menu > li > span:hover { padding-bottom: 5px; } -.prism-container { -// border-bottom: 1px solid @table-divider-color; - margin-bottom: 15px; - padding-bottom: 15px; -} - .multivalue-container > .container-wrapper > div > .added-value-background { background-color: #dff0d8; // green background for new value of multivalue container } @@ -905,13 +916,16 @@ body .treeview-menu > li > span:hover { .prism-properties { - & > div { + + .prism-property { padding-left: 40px; - } - .stripe { - background-color: @table-stripe-bg-color; + &.stripe { + background-color: @table-stripe-bg-color; + } } + + } .prism-header { margin-bottom: 15px; diff --git a/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestIntegrationObjectWrapperFactory.java b/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestIntegrationObjectWrapperFactory.java index 6d9922c615a..a170e3a1140 100644 --- a/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestIntegrationObjectWrapperFactory.java +++ b/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestIntegrationObjectWrapperFactory.java @@ -14,6 +14,9 @@ import java.util.*; import java.util.stream.Collectors; +import com.evolveum.midpoint.gui.api.prism.wrapper.*; +import com.evolveum.midpoint.gui.impl.prism.wrapper.*; + import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; @@ -24,10 +27,9 @@ import com.evolveum.icf.dummy.resource.DummyGroup; import com.evolveum.midpoint.gui.api.prism.*; import com.evolveum.midpoint.gui.api.util.ModelServiceLocator; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.ShadowWrapperFactoryImpl; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; -import com.evolveum.midpoint.gui.impl.prism.*; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.impl.factory.wrapper.ShadowWrapperFactoryImpl; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; import com.evolveum.midpoint.gui.test.TestMidPointSpringApplication; import com.evolveum.midpoint.model.api.ModelExecuteOptions; import com.evolveum.midpoint.prism.*; @@ -108,7 +110,6 @@ public class TestIntegrationObjectWrapperFactory extends AbstractInitializedGuiI OrgType.F_TRIGGER, OrgType.F_AUTOASSIGN, ShadowType.F_CREDENTIALS); - private String userWallyOid; private String accountWallyOid; @@ -166,11 +167,13 @@ public void test100CreateWrapperUserJack() throws Exception { assertEquals("Wrong main container wrapper readOnly", Boolean.FALSE, (Boolean) objectWrapper.isReadOnly()); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_NAME, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_GIVEN_NAME, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_FULL_NAME, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_ADDITIONAL_NAME, false); // not visible, because it is empty - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_LOCALITY, true); + ItemStatus objectStatus = objectWrapper.getStatus(); + + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_NAME, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_GIVEN_NAME, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_FULL_NAME, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_ADDITIONAL_NAME, false); // not visible, because it is empty + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_LOCALITY, true); assertItemWrapperProcessing(mainContainerValueWrapper, extensionPath(PIRACY_WEAPON), null); assertItemWrapperProcessing(mainContainerValueWrapper, extensionPath(PIRACY_COLORS), ItemProcessing.AUTO); @@ -181,11 +184,11 @@ public void test100CreateWrapperUserJack() throws Exception { mainContainerValueWrapper.setShowEmpty(true); // THEN - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_NAME, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_GIVEN_NAME, true); // emphasized - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_FULL_NAME, true); // emphasized - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_ADDITIONAL_NAME, true); // empty - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_LOCALITY, true); // empty + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_NAME, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_GIVEN_NAME, true); // emphasized + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_FULL_NAME, true); // emphasized + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_ADDITIONAL_NAME, true); // empty + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_LOCALITY, true); // empty ObjectDelta objectDelta = objectWrapper.getObjectDelta(); displayDumpable("Delta", objectDelta); @@ -243,21 +246,22 @@ public void test102CreateWrapperUserEmpty() throws Exception { assertEquals("Wrong main container wrapper readOnly", Boolean.FALSE, (Boolean) objectWrapper.isReadOnly()); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_NAME, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_GIVEN_NAME, true); // emphasized - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_FULL_NAME, true); // emphasized - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_ADDITIONAL_NAME, false); // empty - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_LOCALITY, false); // empty + ItemStatus objectStatus = objectWrapper.getStatus(); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_NAME, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_GIVEN_NAME, true); // emphasized + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_FULL_NAME, true); // emphasized + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_ADDITIONAL_NAME, false); // empty + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_LOCALITY, false); // empty // WHEN mainContainerValueWrapper.setShowEmpty(true); // THEN - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_NAME, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_GIVEN_NAME, true); // emphasized - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_FULL_NAME, true); // emphasized - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_ADDITIONAL_NAME, true); // empty - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_LOCALITY, true); // empty + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_NAME, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_GIVEN_NAME, true); // emphasized + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_FULL_NAME, true); // emphasized + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_ADDITIONAL_NAME, true); // empty + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_LOCALITY, true); // empty ObjectDelta objectDelta = objectWrapper.getObjectDelta(); displayDumpable("Delta", objectDelta); @@ -302,10 +306,11 @@ public void test110CreateWrapperUserNewEmpty() throws Exception { assertEquals("Wrong main container wrapper readOnly", Boolean.FALSE, (Boolean) objectWrapper.isReadOnly()); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_NAME, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_GIVEN_NAME, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_FULL_NAME, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_ADDITIONAL_NAME, true); + ItemStatus objectStatus = objectWrapper.getStatus(); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_NAME, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_GIVEN_NAME, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_FULL_NAME, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_ADDITIONAL_NAME, true); assertItemWrapperProcessing(mainContainerValueWrapper, extensionPath(PIRACY_WEAPON), null); assertItemWrapperProcessing(mainContainerValueWrapper, extensionPath(PIRACY_COLORS), ItemProcessing.AUTO); @@ -316,11 +321,11 @@ public void test110CreateWrapperUserNewEmpty() throws Exception { mainContainerValueWrapper.setShowEmpty(false); // THEN - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_NAME, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_GIVEN_NAME, true); // emphasized - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_FULL_NAME, true); // emphasized - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_ADDITIONAL_NAME, false); // empty - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_LOCALITY, false); // empty + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_NAME, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_GIVEN_NAME, true); // emphasized + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_FULL_NAME, true); // emphasized + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_ADDITIONAL_NAME, false); // empty + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_LOCALITY, false); // empty ObjectDelta objectDelta = objectWrapper.getObjectDelta(); displayDumpable("Delta", objectDelta); @@ -379,20 +384,21 @@ public void test112CreateWrapperUserNewman() throws Exception { assertItemWrapperProcessing(mainContainerValueWrapper, extensionPath(PIRACY_SECRET), ItemProcessing.IGNORE); assertItemWrapperProcessing(mainContainerValueWrapper, extensionPath(PIRACY_RANT), ItemProcessing.MINIMAL); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_NAME, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_GIVEN_NAME, true); // emphasized - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_FULL_NAME, true); // emphasized - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_ADDITIONAL_NAME, true); // empty - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_LOCALITY, true); // empty + ItemStatus objectStatus = objectWrapper.getStatus(); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_NAME, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_GIVEN_NAME, true); // emphasized + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_FULL_NAME, true); // emphasized + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_ADDITIONAL_NAME, true); // empty + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_LOCALITY, true); // empty // WHEN mainContainerValueWrapper.setShowEmpty(false); // THEN - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_NAME, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_GIVEN_NAME, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_FULL_NAME, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, UserType.F_ADDITIONAL_NAME, false); // not visible, because it is empty + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_NAME, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_GIVEN_NAME, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_FULL_NAME, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, UserType.F_ADDITIONAL_NAME, false); // not visible, because it is empty ObjectDelta objectDelta = objectWrapper.getObjectDelta(); displayDumpable("Delta", objectDelta); @@ -518,10 +524,11 @@ public void test160CreateWrapperOrgScummBar() throws Exception { assertEquals("Wrong main container wrapper readOnly", Boolean.FALSE, (Boolean) mainContainerValueWrapper.isReadOnly()); - assertItemWrapperFullConrol(mainContainerValueWrapper, OrgType.F_NAME, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, OrgType.F_IDENTIFIER, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, OrgType.F_RISK_LEVEL, false); // not visible, because it is empty - assertItemWrapperFullConrol(mainContainerValueWrapper, OrgType.F_LOCALITY, true); + ItemStatus objectStatus = objectWrapper.getStatus(); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, OrgType.F_NAME, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, OrgType.F_IDENTIFIER, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, OrgType.F_RISK_LEVEL, false); // not visible, because it is empty + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, OrgType.F_LOCALITY, true); assertItemWrapperProcessing(mainContainerValueWrapper, extensionPath(PIRACY_TRANSFORM_DESCRIPTION), null); PrismContainerWrapper transformContainerWrapper = mainContainerValueWrapper.findContainer(extensionPath(PIRACY_TRANSFORM)); @@ -534,10 +541,10 @@ public void test160CreateWrapperOrgScummBar() throws Exception { mainContainerValueWrapper.setShowEmpty(true); // THEN - assertItemWrapperFullConrol(mainContainerValueWrapper, OrgType.F_NAME, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, OrgType.F_IDENTIFIER, true); - assertItemWrapperFullConrol(mainContainerValueWrapper, OrgType.F_RISK_LEVEL, true); // empty - assertItemWrapperFullConrol(mainContainerValueWrapper, OrgType.F_LOCALITY, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, OrgType.F_NAME, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, OrgType.F_IDENTIFIER, true); + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, OrgType.F_RISK_LEVEL, true); // empty + assertItemWrapperFullConrol(mainContainerValueWrapper, objectStatus, OrgType.F_LOCALITY, true); ObjectDelta objectDelta = objectWrapper.getObjectDelta(); displayDumpable("Delta", objectDelta); @@ -868,6 +875,8 @@ public void test800EditSchemaJackPropReadAllModifySomeUser() throws Exception { PrismContainerValueWrapper mainContainerValueWrapper = objectWrapper.getValue(); + ItemStatus objectStatus = objectWrapper.getStatus(); + PrismPropertyWrapper nameWrapper = mainContainerValueWrapper.findProperty(UserType.F_NAME); assertEquals("Wrong name readOnly", Boolean.TRUE, (Boolean) nameWrapper.isReadOnly()); // Is this OK? assertEquals("Wrong name visible", Boolean.TRUE, (Boolean) nameWrapper.isVisible(mainContainerValueWrapper, null)); @@ -937,6 +946,8 @@ public void test802EditSchemaJackPropReadSomeModifySomeUser() throws Exception { displayDumpable("Wrapper after", objectWrapper); assertEquals("Wrong object wrapper readOnly", Boolean.FALSE, (Boolean) objectWrapper.isReadOnly()); + ItemStatus objectStatus = objectWrapper.getStatus(); + PrismContainerValueWrapper mainContainerValueWrapper = objectWrapper.getValue(); PrismPropertyWrapper nameWrapper = mainContainerValueWrapper.findProperty(UserType.F_NAME); assertEquals("Wrong name readOnly", Boolean.TRUE, (Boolean) nameWrapper.isReadOnly()); @@ -983,7 +994,7 @@ public void test802EditSchemaJackPropReadSomeModifySomeUser() throws Exception { // assertEquals("Wrong locality definition.canModify", Boolean.FALSE, (Boolean)localityNameWrapper.canModify()); } - private void assertItemWrapperFullConrol(PrismContainerValueWrapper containerWrapper, ItemName propName, + private void assertItemWrapperFullConrol(PrismContainerValueWrapper containerWrapper, ItemStatus status, ItemName propName, boolean visible) throws SchemaException { ItemWrapper itemWrapper = containerWrapper.findItem(propName, ItemWrapper.class); assertEquals("Wrong " + propName + " readOnly", Boolean.FALSE, (Boolean) itemWrapper.isReadOnly()); @@ -994,7 +1005,7 @@ private void assertItemWrapperFullConrol(PrismContaine } private void assertItemWrapperProcessing(PrismContainerValueWrapper containerWrapper, - ItemPath propName, ItemProcessing expectedProcessing) throws SchemaException { + ItemPath propName, ItemProcessing expectedProcessing) throws SchemaException { ItemWrapper itemWrapper = containerWrapper.findItem(propName, ItemWrapper.class); if (expectedProcessing == ItemProcessing.IGNORE) { assertNull("Unexpected ignored item wrapper for " + propName, itemWrapper); diff --git a/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestPageOrg.java b/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestPageOrg.java index 6636ee7ac11..261a3f84003 100644 --- a/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestPageOrg.java +++ b/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestPageOrg.java @@ -38,7 +38,7 @@ public class TestPageOrg extends AbstractInitializedGuiIntegrationTest { private static final String MAIN_FORM = "mainPanel:mainForm"; // private static final String FORM_INPUT_DESCRIPTION = "tabPanel:panel:basicSystemConfiguration:values:0:value:propertiesLabel:properties:1:property:values:0:valueContainer:form:input:input"; - private static final String PATH_FORM_NAME = "tabPanel:panel:main:values:0:value:propertiesLabel:properties:0:property:values:0:valueContainer:form:input:originValueContainer:origValueWithButton:origValue:input"; + private static final String PATH_FORM_NAME = "tabPanel:panel:main:values:0:value:valueForm:valueContainer:input:propertiesLabel:properties:0:property:values:0:value:valueForm:valueContainer:input:originValueContainer:origValueWithButton:origValue:input"; private static final String FORM_SAVE = "save"; private static final String NEW_ORG_NAME = "A-newOrg"; // starts with "A" to be alphabetically first diff --git a/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestPageRole.java b/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestPageRole.java index 034b4094126..05433c947bd 100644 --- a/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestPageRole.java +++ b/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestPageRole.java @@ -41,7 +41,7 @@ public class TestPageRole extends AbstractInitializedGuiIntegrationTest { private static final String MAIN_FORM = "mainPanel:mainForm"; - private static final String PATH_FORM_NAME = "tabPanel:panel:main:values:0:value:propertiesLabel:properties:0:property:values:0:valueContainer:form:input:originValueContainer:origValueWithButton:origValue:input"; + private static final String PATH_FORM_NAME = "tabPanel:panel:main:values:0:value:valueForm:valueContainer:input:propertiesLabel:properties:0:property:values:0:value:valueForm:valueContainer:input:originValueContainer:origValueWithButton:origValue:input"; private static final String FORM_SAVE = "save"; @Override diff --git a/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestPageSystemConfiguration.java b/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestPageSystemConfiguration.java index ab9a1a7bb72..0d3bc29a087 100644 --- a/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestPageSystemConfiguration.java +++ b/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestPageSystemConfiguration.java @@ -35,7 +35,7 @@ public class TestPageSystemConfiguration extends AbstractInitializedGuiIntegrationTest { private static final String MAIN_FORM = "mainPanel:mainForm"; - private static final String FORM_INPUT_DESCRIPTION = "tabPanel:panel:basicSystemConfiguration:values:0:value:propertiesLabel:properties:1:property:values:0:valueContainer:form:input:input"; + private static final String FORM_INPUT_DESCRIPTION = "tabPanel:panel:basicSystemConfiguration:values:0:value:valueForm:valueContainer:input:propertiesLabel:properties:1:property:values:0:value:valueForm:valueContainer:input:input"; private static final String FORM_SAVE = "save"; @Override @@ -56,7 +56,7 @@ public void test000testPageSystemConfiguration() { public void test001testModifySystemConfig() throws Exception { renderPage(); - tester.clickLink(MAIN_FORM + ":tabPanel:panel:basicSystemConfiguration:values:0:value:showEmptyButton"); + tester.clickLink(MAIN_FORM + ":tabPanel:panel:basicSystemConfiguration:values:0:value:valueForm:valueContainer:input:propertiesLabel:showEmptyButton"); FormTester formTester = tester.newFormTester(MAIN_FORM, false); String des = "new description"; diff --git a/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestPageUser.java b/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestPageUser.java index d7162df27af..c9da5ea9bb3 100644 --- a/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestPageUser.java +++ b/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestPageUser.java @@ -22,7 +22,7 @@ import com.evolveum.midpoint.gui.impl.component.MultivalueContainerDetailsPanel; import com.evolveum.midpoint.gui.impl.component.MultivalueContainerListPanelWithDetailsPanel; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerPanel; +import com.evolveum.midpoint.gui.impl.prism.panel.PrismContainerPanel; import com.evolveum.midpoint.gui.test.TestMidPointSpringApplication; import com.evolveum.midpoint.model.api.ModelExecuteOptions; import com.evolveum.midpoint.prism.PrismObject; diff --git a/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestWrapperDelta.java b/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestWrapperDelta.java index 072773ff21d..ccc5ad74b49 100644 --- a/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestWrapperDelta.java +++ b/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/TestWrapperDelta.java @@ -7,16 +7,15 @@ package com.evolveum.midpoint.gui; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.ModelServiceLocator; -import com.evolveum.midpoint.gui.api.util.WebPrismUtil; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.ProfilingClassLoggerWrapperFactoryImpl; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.impl.factory.wrapper.ProfilingClassLoggerWrapperFactoryImpl; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.impl.prism.wrapper.PrismPropertyValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; import com.evolveum.midpoint.gui.test.TestMidPointSpringApplication; import com.evolveum.midpoint.model.api.ModelExecuteOptions; import com.evolveum.midpoint.prism.*; @@ -37,7 +36,6 @@ import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.web.AbstractInitializedGuiIntegrationTest; import com.evolveum.midpoint.web.component.prism.ValueStatus; -import com.evolveum.midpoint.web.page.admin.reports.dto.ReportDeleteDialogDto; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import com.evolveum.prism.xml.ns._public.types_3.ItemPathType; import com.evolveum.prism.xml.ns._public.types_3.ModificationTypeType; diff --git a/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/test/TestMidPointSpringApplication.java b/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/test/TestMidPointSpringApplication.java index c57e0b00907..bb847bd813f 100644 --- a/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/test/TestMidPointSpringApplication.java +++ b/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/test/TestMidPointSpringApplication.java @@ -23,7 +23,7 @@ import org.springframework.context.annotation.ImportResource; import org.springframework.context.annotation.Profile; -import com.evolveum.midpoint.gui.impl.factory.TextAreaPanelFactory; +import com.evolveum.midpoint.gui.impl.factory.panel.TextAreaPanelFactory; import com.evolveum.midpoint.gui.impl.registry.GuiComponentRegistryImpl; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; diff --git a/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/AbstractGuiIntegrationTest.java b/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/AbstractGuiIntegrationTest.java index 08679f64aed..abbf7f4447d 100644 --- a/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/AbstractGuiIntegrationTest.java +++ b/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/AbstractGuiIntegrationTest.java @@ -28,14 +28,14 @@ import com.evolveum.midpoint.common.LocalizationService; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; import com.evolveum.midpoint.gui.api.registry.GuiComponentRegistry; import com.evolveum.midpoint.gui.api.util.ModelServiceLocator; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.factory.ItemWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; +import com.evolveum.midpoint.gui.api.factory.wrapper.ItemWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; import com.evolveum.midpoint.model.api.ModelInteractionService; import com.evolveum.midpoint.model.api.ModelService; import com.evolveum.midpoint.model.api.authentication.CompiledGuiProfile; @@ -225,15 +225,15 @@ public PrismObjectWrapperFactory findObjectWrapperFact @Override public IW createItemWrapper(I item, ItemStatus status, WrapperContext ctx) throws SchemaException { - ItemWrapperFactory factory = (ItemWrapperFactory) registry.findWrapperFactory(item.getDefinition()); + ItemWrapperFactory factory = registry.findWrapperFactory(item.getDefinition()); ctx.setCreateIfEmpty(true); - return factory.createWrapper(item, status, ctx); + return factory.createWrapper(null, item, status, ctx); } @Override public VW createValueWrapper(IW parentWrapper, PV newValue, ValueStatus status, WrapperContext context) throws SchemaException { - ItemWrapperFactory factory = (ItemWrapperFactory) registry.findWrapperFactory(parentWrapper); + ItemWrapperFactory factory = registry.findWrapperFactory(parentWrapper); return factory.createValueWrapper(parentWrapper, newValue, status, context); } diff --git a/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/AbstractGuiUnitTest.java b/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/AbstractGuiUnitTest.java index c29675aa029..d0f1f9f1ec5 100644 --- a/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/AbstractGuiUnitTest.java +++ b/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/AbstractGuiUnitTest.java @@ -10,10 +10,10 @@ import java.util.Locale; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.factory.wrapper.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; import com.evolveum.midpoint.prism.Item; import com.evolveum.midpoint.prism.PrismObjectDefinition; import com.evolveum.midpoint.prism.PrismValue; diff --git a/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/WrapperTestUtil.java b/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/WrapperTestUtil.java index 29dfe18518f..ad4a44fcb98 100644 --- a/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/WrapperTestUtil.java +++ b/gui/admin-gui/src/test/java/com/evolveum/midpoint/web/WrapperTestUtil.java @@ -14,13 +14,13 @@ import org.testng.AssertJUnit; import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.ItemWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismObjectWrapper; import com.evolveum.midpoint.gui.api.util.ModelServiceLocator; -import com.evolveum.midpoint.gui.impl.prism.PrismContainerValueWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismPropertyWrapper; -import com.evolveum.midpoint.gui.impl.prism.PrismValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismPropertyWrapper; +import com.evolveum.midpoint.gui.api.prism.wrapper.PrismValueWrapper; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.path.ItemName; import com.evolveum.midpoint.prism.path.ItemPath; diff --git a/infra/prism-api/pom.xml b/infra/prism-api/pom.xml index e30b0ea73f9..a7095521a21 100644 --- a/infra/prism-api/pom.xml +++ b/infra/prism-api/pom.xml @@ -58,10 +58,6 @@ org.jvnet.jaxb2_commons jaxb2-basics-runtime - - javax.xml.soap - javax.xml.soap-api - com.sun.activation javax.activation diff --git a/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/Hacks.java b/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/Hacks.java index 99ee1dff363..aa45b8e66fb 100644 --- a/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/Hacks.java +++ b/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/Hacks.java @@ -7,28 +7,22 @@ package com.evolveum.midpoint.prism; -import com.evolveum.midpoint.prism.xnode.MapXNode; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.prism.xml.ns._public.types_3.ProtectedDataType; import com.google.common.annotations.VisibleForTesting; - import org.w3c.dom.Element; -import javax.xml.namespace.QName; -import javax.xml.soap.Detail; +import com.evolveum.midpoint.prism.xnode.MapXNode; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.prism.xml.ns._public.types_3.ProtectedDataType; /** * TEMPORARY. - * + *

* This interface belongs to a coursebook on Software Engineering as a horrific design example ;) - * + *

* Prism API and/or client code should be modified to get rid of these hacks. */ public interface Hacks { - void serializeFaultMessage(Detail detail, Object faultInfo, QName faultMessageElementName, Trace logger); - @VisibleForTesting void parseProtectedType(ProtectedDataType protectedType, MapXNode xmap, PrismContext prismContext, ParsingContext pc) throws SchemaException; diff --git a/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/SerializationOptions.java b/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/SerializationOptions.java index 3842bed905c..d6d67635e68 100644 --- a/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/SerializationOptions.java +++ b/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/SerializationOptions.java @@ -7,8 +7,10 @@ package com.evolveum.midpoint.prism; +import com.evolveum.midpoint.util.annotation.Experimental; + /** - * @author Pavol Mederly + * */ public class SerializationOptions implements Cloneable { @@ -29,6 +31,14 @@ public class SerializationOptions implements Cloneable { */ private boolean serializeForExport; + /** + * Works around characters that cannot be serialized in XML by replacing them with acceptable form. + * Because the result is not machine processable it should be used with caution; for example only + * for logging, tracing, or maybe auditing purposes. + */ + @Experimental + private boolean escapeInvalidCharacters; + // private NameQualificationStrategy itemTypeQualificationStrategy; // private NameQualificationStrategy itemPathQualificationStrategy; // private NameQualificationStrategy genericQualificationStrategy; @@ -117,6 +127,27 @@ public static boolean isSerializeForExport(SerializationOptions options) { return options != null && options.isSerializeForExport(); } + public boolean isEscapeInvalidCharacters() { + return escapeInvalidCharacters; + } + + public void setEscapeInvalidCharacters(boolean escapeInvalidCharacters) { + this.escapeInvalidCharacters = escapeInvalidCharacters; + } + + public SerializationOptions escapeInvalidCharacters(boolean value) { + setEscapeInvalidCharacters(value); + return this; + } + + public static SerializationOptions createEscapeInvalidCharacters() { + return new SerializationOptions().escapeInvalidCharacters(true); + } + + public static boolean isEscapeInvalidCharacters(SerializationOptions options) { + return options != null && options.isEscapeInvalidCharacters(); + } + public void setSkipIndexOnly(boolean skipIndexOnly) { this.skipIndexOnly = skipIndexOnly; } @@ -203,6 +234,7 @@ public String toString() { ", skipIndexOnly=" + skipIndexOnly + ", itemNameQualificationStrategy=" + itemNameQualificationStrategy + ", serializeForExport=" + serializeForExport + + ", escapeInvalidCharacters=" + escapeInvalidCharacters + '}'; } } diff --git a/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/xml/XmlTypeConverter.java b/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/xml/XmlTypeConverter.java index 4bcfc6cd21c..a288a974b8b 100644 --- a/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/xml/XmlTypeConverter.java +++ b/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/xml/XmlTypeConverter.java @@ -190,11 +190,20 @@ public static XMLGregorianCalendar fromNow(String timeSpec) { } public static XMLGregorianCalendar fromNow(Duration duration) { - XMLGregorianCalendar rv = createXMLGregorianCalendar(System.currentTimeMillis()); + return fromNow(System.currentTimeMillis(), duration); + } + + public static XMLGregorianCalendar fromNow(long now, Duration duration) { + XMLGregorianCalendar rv = createXMLGregorianCalendar(now); rv.add(duration); return rv; } + public static long toMillis(Duration duration) { + long now = System.currentTimeMillis(); + return toMillis(fromNow(now, duration)) - now; + } + public static Duration createDuration(long durationInMilliSeconds) { return getDatatypeFactory().newDuration(durationInMilliSeconds); } diff --git a/infra/prism-impl/pom.xml b/infra/prism-impl/pom.xml index 6d707f84b46..dba103b4b05 100644 --- a/infra/prism-impl/pom.xml +++ b/infra/prism-impl/pom.xml @@ -125,11 +125,6 @@ jackson-dataformat-yaml - - javax.xml.soap - javax.xml.soap-api - - org.testng diff --git a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/HacksImpl.java b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/HacksImpl.java index 618db62dff5..61212ad6e94 100644 --- a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/HacksImpl.java +++ b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/HacksImpl.java @@ -7,21 +7,23 @@ package com.evolveum.midpoint.prism.impl; +import javax.xml.namespace.QName; + +import org.jetbrains.annotations.NotNull; +import org.w3c.dom.Element; + import com.evolveum.midpoint.prism.Hacks; import com.evolveum.midpoint.prism.ParsingContext; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.impl.lex.dom.DomLexicalProcessor; import com.evolveum.midpoint.prism.impl.marshaller.XNodeProcessorUtil; -import com.evolveum.midpoint.prism.impl.xnode.*; +import com.evolveum.midpoint.prism.impl.xnode.ListXNodeImpl; +import com.evolveum.midpoint.prism.impl.xnode.MapXNodeImpl; +import com.evolveum.midpoint.prism.impl.xnode.PrimitiveXNodeImpl; +import com.evolveum.midpoint.prism.impl.xnode.XNodeImpl; import com.evolveum.midpoint.prism.xnode.*; import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.prism.xml.ns._public.types_3.ProtectedDataType; -import org.jetbrains.annotations.NotNull; -import org.w3c.dom.Element; - -import javax.xml.namespace.QName; -import javax.xml.soap.Detail; /** * TEMPORARY @@ -34,23 +36,6 @@ public class HacksImpl implements Hacks, XNodeMutator { this.prismContext = prismContext; } - /** - * TODO rewrite this method using Prism API - */ - @Override - public void serializeFaultMessage(Detail detail, Object faultInfo, QName faultMessageElementName, Trace logger) { - try { - XNodeImpl faultMessageXnode = prismContext.getBeanMarshaller().marshall(faultInfo); - RootXNodeImpl xroot = new RootXNodeImpl(faultMessageElementName, faultMessageXnode); - xroot.setExplicitTypeDeclaration(true); - QName faultType = prismContext.getSchemaRegistry().determineTypeForClass(faultInfo.getClass()); - xroot.setTypeQName(faultType); - prismContext.getParserDom().serializeUnderElement(xroot, faultMessageElementName, detail); - } catch (SchemaException e) { - logger.error("Error serializing fault message (SOAP fault detail): {}", e.getMessage(), e); - } - } - @Override public void setPrimitiveXNodeValue(PrimitiveXNode node, T value, QName typeName) { ((PrimitiveXNodeImpl) node).setValue(value, typeName); diff --git a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/lex/dom/DomLexicalProcessor.java b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/lex/dom/DomLexicalProcessor.java index eb84797b6ea..8dc80a55c50 100644 --- a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/lex/dom/DomLexicalProcessor.java +++ b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/lex/dom/DomLexicalProcessor.java @@ -422,7 +422,7 @@ public boolean canRead(@NotNull String dataString) { @NotNull @Override public String write(@NotNull XNode xnode, @NotNull QName rootElementName, SerializationContext serializationContext) throws SchemaException { - DomLexicalWriter serializer = new DomLexicalWriter(schemaRegistry); + DomLexicalWriter serializer = new DomLexicalWriter(schemaRegistry, serializationContext); RootXNodeImpl xroot = LexicalUtils.createRootXNode((XNodeImpl) xnode, rootElementName); Element element = serializer.serialize(xroot); return DOMUtil.serializeDOMToString(element); @@ -431,7 +431,7 @@ public String write(@NotNull XNode xnode, @NotNull QName rootElementName, Serial @NotNull @Override public String write(@NotNull RootXNode xnode, SerializationContext serializationContext) throws SchemaException { - DomLexicalWriter serializer = new DomLexicalWriter(schemaRegistry); + DomLexicalWriter serializer = new DomLexicalWriter(schemaRegistry, serializationContext); Element element = serializer.serialize((RootXNodeImpl) xnode); return DOMUtil.serializeDOMToString(element); } @@ -446,29 +446,23 @@ public String write(@NotNull List roots, @Nullable QName aggregat @NotNull public Element writeXRootListToElement(@NotNull List roots, QName aggregateElementName) throws SchemaException { - DomLexicalWriter serializer = new DomLexicalWriter(schemaRegistry); + DomLexicalWriter serializer = new DomLexicalWriter(schemaRegistry, null); return serializer.serialize(roots, aggregateElementName); } - public Element serializeUnderElement(XNodeImpl xnode, QName rootElementName, Element parentElement) throws SchemaException { - DomLexicalWriter serializer = new DomLexicalWriter(schemaRegistry); - RootXNodeImpl xroot = LexicalUtils.createRootXNode(xnode, rootElementName); - return serializer.serializeUnderElement(xroot, parentElement); - } - public Element serializeXMapToElement(MapXNodeImpl xmap, QName elementName) throws SchemaException { - DomLexicalWriter serializer = new DomLexicalWriter(schemaRegistry); + DomLexicalWriter serializer = new DomLexicalWriter(schemaRegistry, null); return serializer.serializeToElement(xmap, elementName); } private Element serializeXPrimitiveToElement(PrimitiveXNodeImpl xprim, QName elementName) throws SchemaException { - DomLexicalWriter serializer = new DomLexicalWriter(schemaRegistry); + DomLexicalWriter serializer = new DomLexicalWriter(schemaRegistry, null); return serializer.serializeXPrimitiveToElement(xprim, elementName); } @NotNull public Element writeXRootToElement(@NotNull RootXNodeImpl xroot) throws SchemaException { - DomLexicalWriter serializer = new DomLexicalWriter(schemaRegistry); + DomLexicalWriter serializer = new DomLexicalWriter(schemaRegistry, null); return serializer.serialize(xroot); } diff --git a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/lex/dom/DomLexicalWriter.java b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/lex/dom/DomLexicalWriter.java index 07d63894abc..204534e804a 100644 --- a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/lex/dom/DomLexicalWriter.java +++ b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/lex/dom/DomLexicalWriter.java @@ -6,6 +6,8 @@ */ package com.evolveum.midpoint.prism.impl.lex.dom; +import com.evolveum.midpoint.prism.SerializationContext; +import com.evolveum.midpoint.prism.SerializationOptions; import com.evolveum.midpoint.prism.impl.PrismContextImpl; import com.evolveum.midpoint.prism.impl.marshaller.ItemPathHolder; import com.evolveum.midpoint.prism.schema.SchemaRegistry; @@ -45,11 +47,13 @@ public class DomLexicalWriter { private Document doc; private boolean serializeCompositeObjects = false; - private SchemaRegistry schemaRegistry; + private final SchemaRegistry schemaRegistry; + private final SerializationOptions serializationOptions; - DomLexicalWriter(SchemaRegistry schemaRegistry) { + DomLexicalWriter(SchemaRegistry schemaRegistry, SerializationContext context) { super(); this.schemaRegistry = schemaRegistry; + this.serializationOptions = context != null ? context.getOptions() : null; } public boolean isSerializeCompositeObjects() { @@ -318,11 +322,12 @@ private void serializePrimitiveElementOrAttribute(PrimitiveXNodeImpl xprim, E } else { // not ItemType nor QName String value = xprim.getGuessedFormattedValue(); - + String fixedValue = SerializationOptions.isEscapeInvalidCharacters(serializationOptions) ? + DOMUtil.escapeInvalidXmlCharsIfPresent(value) : value; if (asAttribute) { - DOMUtil.setAttributeValue(parentElement, elementOrAttributeName.getLocalPart(), value); + DOMUtil.setAttributeValue(parentElement, elementOrAttributeName.getLocalPart(), fixedValue); } else { - DOMUtil.setElementTextContent(element, value); + DOMUtil.setElementTextContent(element, fixedValue); } } diff --git a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/xjc/PrismForJAXBUtil.java b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/xjc/PrismForJAXBUtil.java index 3b6013562a0..66d052debb2 100644 --- a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/xjc/PrismForJAXBUtil.java +++ b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/xjc/PrismForJAXBUtil.java @@ -396,4 +396,7 @@ public static void accept(Object object, JaxbVisitor visitor) { } } + public static SearchFilterType getFilter(PrismReferenceValue referenceValue) { + return referenceValue.getFilter(); + } } diff --git a/infra/schema-pure-jaxb/pom.xml b/infra/schema-pure-jaxb/pom.xml index fe63f576934..0b5dcfc6ba6 100644 --- a/infra/schema-pure-jaxb/pom.xml +++ b/infra/schema-pure-jaxb/pom.xml @@ -168,12 +168,13 @@ public.annotation-3\.xsd query-3\.xsd - \\types-3\.xsd - /types-3\.xsd + \\types-3\.xsd + /types-3\.xsd common-.*\.xsd /scripting/.* \\scripting\\.* resource-schema-3\.xsd + api-types-3\.xsd diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/DeltaConversionOptions.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/DeltaConversionOptions.java index f864620c63a..67c9e026c7c 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/DeltaConversionOptions.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/DeltaConversionOptions.java @@ -7,13 +7,23 @@ package com.evolveum.midpoint.schema; +import com.evolveum.midpoint.util.annotation.Experimental; + /** - * @author Pavol Mederly + * Options used when serializing deltas to "bean" form (ObjectDeltaType). */ public class DeltaConversionOptions { private boolean serializeReferenceNames; + /** + * Works around characters that cannot be serialized in XML by replacing them with appropriate + * form. The result will not be machine processable, so it should be used with caution: for example + * only for logging, tracing, or maybe auditing purposes. + */ + @Experimental + private boolean escapeInvalidCharacters; + public boolean isSerializeReferenceNames() { return serializeReferenceNames; } @@ -31,4 +41,16 @@ public static DeltaConversionOptions createSerializeReferenceNames() { options.setSerializeReferenceNames(true); return options; } + + public boolean isEscapeInvalidCharacters() { + return escapeInvalidCharacters; + } + + public void setEscapeInvalidCharacters(boolean escapeInvalidCharacters) { + this.escapeInvalidCharacters = escapeInvalidCharacters; + } + + public static boolean isEscapeInvalidCharacters(DeltaConversionOptions options) { + return options != null && options.isEscapeInvalidCharacters(); + } } diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/DeltaConvertor.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/DeltaConvertor.java index 8d7eb58c7a2..94e5bc2dd78 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/DeltaConvertor.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/DeltaConvertor.java @@ -229,9 +229,11 @@ public static String toObjectDeltaTypeXml(ObjectDelta delt public static String toObjectDeltaTypeXml(ObjectDelta delta, DeltaConversionOptions options) throws SchemaException, JAXBException { Validate.notNull(delta.getPrismContext(), "ObjectDelta without prismContext cannot be converted to XML"); ObjectDeltaType objectDeltaType = toObjectDeltaType(delta, options); - SerializationOptions serializationOptions = new SerializationOptions(); - serializationOptions.setSerializeReferenceNames(DeltaConversionOptions.isSerializeReferenceNames(options)); - return delta.getPrismContext().xmlSerializer().options(serializationOptions).serializeRealValue(objectDeltaType, SchemaConstants.T_OBJECT_DELTA); + SerializationOptions serializationOptions = new SerializationOptions() + .serializeReferenceNames(DeltaConversionOptions.isSerializeReferenceNames(options)) + .escapeInvalidCharacters(DeltaConversionOptions.isEscapeInvalidCharacters(options)); + return delta.getPrismContext().xmlSerializer().options(serializationOptions) + .serializeRealValue(objectDeltaType, SchemaConstants.T_OBJECT_DELTA); } diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/SystemConfigurationAuditUtil.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/SystemConfigurationAuditUtil.java new file mode 100644 index 00000000000..f1ef8ab2b1c --- /dev/null +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/SystemConfigurationAuditUtil.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.schema.util; + +import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationAuditType; + +import org.apache.commons.lang3.ObjectUtils; + +/** + * Utility methods for audit-related system configuration options. + */ +public class SystemConfigurationAuditUtil { + + public static boolean isEscapingInvalidCharacters(SystemConfigurationAuditType configuration) { + final boolean defaultValue = false; + if (configuration == null || configuration.getEventRecording() == null) { + return defaultValue; + } else { + return ObjectUtils.defaultIfNull(configuration.getEventRecording().isEscapeIllegalCharacters(), defaultValue); + } + } +} 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 15914add7c1..f4ef4d379c4 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 @@ -16383,6 +16383,20 @@ + + + + Should illegal characters (like majority of 0x00-0x1F in XML 1.0) be escaped? + If they occur and are not escaped, audit operation will fail. If they are stored + in escaped form, audit operation will succeed but some parts of the audit records + will not be correctly machine processable in the future. So the default value is "false". + + + 4.2 + SystemConfigurationAuditEventRecordingType.escapeIllegalCharacters + + + @@ -20012,7 +20026,6 @@ - @@ -20072,13 +20085,6 @@ - - - - - - - @@ -26563,5 +26569,49 @@ + + + + + Deals with creation of recompute triggers for selected objects. + These triggers can be created in "raw" way, simply by adding respective + TriggerType objects. Or, they can be created in so called optimized way, where + we look if a compatible trigger already exists and skip trigger creation in such + case. + + This structure deals with recompute triggers for now. In might be generalized + in the future. + + + 4.0 + true + true + + + + + + + How long after current time the trigger should be fired. When not specified, + trigger is created unconditionally ("raw" way), with the fire time being + equal to the current time. If specified, the trigger is created with the + fire time in the future; skipping the creation if compatible trigger was + created and still has not been fired. + + + + + + + What is the safety margin, i.e. how many long before the trigger fire time + we need to create a new trigger. This is to avoid (rare but in theory possible) + race conditions where we skip creation of a trigger but it fires in the meanwhile. + + + + + + + diff --git a/infra/schema/src/main/resources/xml/ns/public/model/scripting/scripting-3.xsd b/infra/schema/src/main/resources/xml/ns/public/model/scripting/scripting-3.xsd index e8785af176f..7240ed0f14f 100644 --- a/infra/schema/src/main/resources/xml/ns/public/model/scripting/scripting-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/model/scripting/scripting-3.xsd @@ -1,603 +1,1156 @@ - - - - - - - - - Schema for midPoint scripting language. - - Recommended namespace prefix: s - - - - - - - Common prism annotations used in various XSD schemas. - - - - - - - - Prism data types. - - - - - - - - Prism data types. - - - - - - - - Common midPoint schema. - - - - - - - - Options related to evaluation of scripting expression. - EXPERIMENTAL - In the future, these may become part of any scripting expression, allowing parts of a complex expression - to be evaluated differently from its other parts. - - - - - - - - - Causes evaluation to continue even in the presence of any errors. - TODO make this more elaborate w.r.t. kind of error(s) encountered. - - - - - - - Hides operation results from the output data. - - - - - - - - - - Definition of scripting variables. - - - 3.7 - - - - - - - - - - - - Definition of a scripting variable. - Expression types other than path-based ones are to be considered EXPERIMENTAL. - - - 3.7 - - - - - - - - - Type of the variable. Can be omitted for path expressions. EXPERIMENTAL. - - - - - - - Multiplicity specification. Can be omitted for path expressions. EXPERIMENTAL. - - - - - - - - - - - - - Root of the expression type inheritance hierarchy. - - - - - - - - - - Sequence of command expressions - they are executed one after another, - input sent to the sequence as a whole is then sent individually - to each expression. Output of the last expression is considered to be the output of - the whole sequence. - - - - - - - - - - - - - - - - - - - - - - - Pipeline of expressions - they are executed one after another, - input sent to the pipeline as a whole is sent to the first expression. - Output from the N-th expression is sent as an input to the N+1-th expression. - Output of the last expression is considered to be the output of the whole - pipeline. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Queries the model for objects of a given type, optionally fulfilling given condition. - - - - - - - - - Type whose instances are searched for. - - - - - - - Variable to hold found instances. Not yet supported. - - - - - - - Query to apply when searching for instances. (Alternative to searchFilter. This is tried as the first one.) - - - - - - - Filter to apply when searching for instances. (Alternative to query. This is tried as second one.) - - - - - - - Filter to apply when searching for instances. (Alternative to query. This is tried as second one.) - - - - - - - Action parameters. - - - - - - - Expression to evaluate for each object found. - - - - - - - Whether to aggregate and pass forward the output of expression evaluations that are done - for each object found. (Meaningful only if scriptingExpression is specified.) - Default is true for compatibility reasons. Set to false to optimize memory consumption. - - - 3.7.1 - - - - - - - - - - - - - - - - - - - Filters input on a given condition. - - - - - - - - - Filter to apply to the input stream. - - - - - - - - - - - - - - - - - - - Select given item. - - - - - - - - - Path to the data item that has to be selected. - - - - - - - - - - - - - - - - - - - Keeps/removes selected items from the input value. - - - - - - - - - Path to the data item(s) that should be kept. - - - - - - - Path to the data item(s) that should be removed. - - - - - - - - - - - - - - - - - - - Executes a given command individually for each item arriving at the input. - - - - - - - - - Variable to hold emitted instances. - - - - - - - - - - - - - - - - - - - - Executes a given action (add, modify, delete, enable, disable, assign, ...) - - - - - - - - - Action to execute. - - - - - - - Action parameters. - - - - - - - - - - - - - - - - - - - Value of a parameter for an action. - - - - - - - Parameter name. - - - - - - - - - Parameter (argument) value. - - - - - - - - - - - - - - - - - - 3.7 - - - - - - - - - - - Output of a single script execution. - - - 3.6 - - - - - - - Data output of the execution of the script. - - - - - - - Text ("console") output of the execution of the script. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TODO - - - - - - - - - - TODO - - - - - - - + + + + + + + + + Schema for midPoint scripting language. + + Recommended namespace prefix: s + + + + + + + Common prism annotations used in various XSD schemas. + + + + + + + + Prism data types. + + + + + + + + Prism data types. + + + + + + + + Common midPoint schema. + + + + + + + + + + Options related to evaluation of scripting expression. + EXPERIMENTAL + In the future, these may become part of any scripting expression, allowing parts of a complex expression + to be evaluated differently from its other parts. + + + + + + + + + Causes evaluation to continue even in the presence of any errors. + TODO make this more elaborate w.r.t. kind of error(s) encountered. + + + + + + + Hides operation results from the output data. + + + + + + + + + + Definition of scripting variables. + + + 3.7 + + + + + + + + + + + + Definition of a scripting variable. + Expression types other than path-based ones are to be considered EXPERIMENTAL. + + + 3.7 + + + + + + + + + Type of the variable. Can be omitted for path expressions. EXPERIMENTAL. + + + + + + + Multiplicity specification. Can be omitted for path expressions. EXPERIMENTAL. + + + + + + + + + + + + + Root of the expression type inheritance hierarchy. + + + + + + + + + + Sequence of command expressions - they are executed one after another, + input sent to the sequence as a whole is then sent individually + to each expression. Output of the last expression is considered to be the output of + the whole sequence. + + + + + + + + + + + + + + + + + + + + + + + Pipeline of expressions - they are executed one after another, + input sent to the pipeline as a whole is sent to the first expression. + Output from the N-th expression is sent as an input to the N+1-th expression. + Output of the last expression is considered to be the output of the whole + pipeline. + + + + + + + + + + + + + + + + + + + + + + + Queries the model for objects of a given type, optionally fulfilling given condition. + + + + + + + + + Type whose instances are searched for. + + + + + + + Variable to hold found instances. Not yet supported. + + + + + + + Query to apply when searching for instances. (Alternative to searchFilter. This is tried as the first one.) + + + + + + + Filter to apply when searching for instances. (Alternative to query. This is tried as second one.) + + + + + + + Options to use when executing the search. + + + + + + + Action parameters. + + + + + + + Expression to evaluate for each object found. + + + + + + + Whether to aggregate and pass forward the output of expression evaluations that are done + for each object found. (Meaningful only if scriptingExpression is specified.) + Default is true for compatibility reasons. Set to false to optimize memory consumption. + + + 3.7.1 + + + + + + + + + + + + + + + + + + + Filters input on a given condition. + + + + + + + + + Filter to apply to the input stream. + + + + + + + + + + + + + + + + + + + Select given item. + + + + + + + + + Path to the data item that has to be selected. + + + + + + + + + + + + + + + + + + + Keeps/removes selected items from the input value. + + + + + + + + + Path to the data item(s) that should be kept. + + + + + + + Path to the data item(s) that should be removed. + + + + + + + + + + + + + + + + + + + Executes a given command individually for each item arriving at the input. + + + + + + + + + Variable to hold emitted instances. + + + + + + + + + + + + + + + + + + + + Executes a given action (add, modify, delete, enable, disable, assign, ...) + + + + + + + + + Action to execute. + + + + + + + Action parameters. + + + + + + + + + + + + + + + + + + + Value of a parameter for an action. + + + + + + + Parameter name. + + + + + + + + + Parameter (argument) value. + + + + + + + + + + + Supertype for "execution" actions, carrying some common properties. + + + 4.2 + true + + + + + + + + + Model execute options. + + + + + + + Should the action be only previewed (run as "dry")? + + + + + + + + + + + + Statically-typed "add" action. + + + 4.2 + true + + + + + + + + + + + + + + + + + + + Statically-typed "apply-definition" action. + + + 4.2 + true + + + + + + + + + + + + + + + + + + Statically-typed "assign" action. Its parameters differ significantly from the + parameters of dynamically-type assign action, because the latter ones were not + designed well. + + + 4.2 + true + + + + + + + + + Target(s) to be assigned. May contain filters. If such filters are present, they + are evaluated at action execution time. (This behavior may change in the future!) + If relations other than default are to be used, they should be provided within the reference(s). + + + + + + + Resource(s) to be assigned. May contain filters. If such filters are present, they + are evaluated at action execution time. (This behavior may change in the future!) + + + + + + + Resource object constructions to be assigned. These are assigned "as is", with no + filter evaluation. (This behavior may change in the future!) + + + + + + + + + + + + + + + + + + + Statically-typed "delete" action. + + + 4.2 + true + + + + + + + + + + + + + + + + + + + Statically-typed "disable" action. + + + 4.2 + true + + + + + + + + + + + + + + + + + + + Statically-typed "enable" action. + + + 4.2 + true + + + + + + + + + + + + + + + + + + + Statically-typed "execute-script" action. + + + 4.2 + true + + + + + + + + + Script to be executed. + + + + + + + If the script produces any output, this is a specification of an item (property, reference, + container, or object) that provides a definition for the output. EXPERIMENTAL. + + + + + + + If the script produces any output, this is a specification of a simple or complex type + that provides a definition for the output. EXPERIMENTAL. + + + + + + + Should we execute the script for the whole input (true) or for each individual input item (false)? + + + + + + + If true, console output is suppressed. + + + + + + + + + + + + + + + + + + + Statically-typed "generate-values" action. + + + 4.2 + true + + + + + + + + + Defined items and rules for generating/validating values. + + + + + + + + + + + + + + + + + + + Statically-typed "log" action. + + + 4.2 + true + + + + + + + + + Message to be logged. + + + + + + + Level on which the message should be logged. + We use xsd:string here just for compatibility with the + dynamic variant. In the future we will switch to c:LoggingLevelType. + + + + + + + + + + + + + + + + + + + Statically-typed "modify" action. + + + 4.2 + true + + + + + + + + + Delta to be applied. + + + + + + + + + + + + + + + + + + + Statically-typed "notify" action. + + + 4.2 + true + + + + + + + + + Subtype of the event created: Free-text information about category (type) + of this custom event. + + + + + + + Operation to be put into event (add, modify, delete). Default is "add". + + + + + + + Status to be put into event (success, failure, inProgress, alsoSuccess, onlyFailure). + Default is "success". + + + + + + + Ad-hoc event handler that should be used to process the event. + If not specified, system configuration is used to determine the handler(s). + + + + + + + Whole input (i.e. all items in the pipeline) should be sent as event object. + The default behavior is to generate one event for each input object. + + + + + + + + + + + + + + + + + + + Statically-typed "purge-schema" action. + + + 4.2 + true + + + + + + + + + + + + + + + + + + Statically-typed "recompute" action. + + + 4.2 + true + + + + + + + + + Does not invoke recompute immediately but uses a trigger to do that. + + + + + + + + + + + + + + + + + + + Statically-typed "resolve" action. + + + 4.2 + true + + + + + + + + + Options to use when getting the object(s). + + + + + + + + + + + + + + + + + + + Statically-typed "resume" action. + + + 4.2 + true + + + + + + + + + + + + + + + + + + Statically-typed "test-resource" action. + + + 4.2 + true + + + + + + + + + + + + + + + + + + Statically-typed "unassign" action. + + + 4.2 + true + + + + + + + + + Filter matching assignments to be deleted. + + + + + + + + + + + + + + + + + + + + + + + + 3.7 + + + + + + + + + + + Output of a single script execution. + + + 3.6 + + + + + + + Data output of the execution of the script. + + + + + + + Text ("console") output of the execution of the script. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TODO + + + + + + + + + + TODO + + + + + + + diff --git a/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestMiscellaneous.java b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestMiscellaneous.java index 6fd16d4fa40..ab9e478f6a7 100644 --- a/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestMiscellaneous.java +++ b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestMiscellaneous.java @@ -6,6 +6,7 @@ */ package com.evolveum.midpoint.schema; +import static org.assertj.core.api.Assertions.assertThat; import static org.testng.AssertJUnit.*; import static com.evolveum.midpoint.prism.util.PrismTestUtil.getPrismContext; @@ -20,9 +21,6 @@ import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -/** - * @author mederly - */ public class TestMiscellaneous extends AbstractSchemaTest { public static final File TEST_DIR = new File("src/test/resources/misc"); @@ -86,4 +84,15 @@ public void removeOperationalItems() throws Exception { assertEquals("Wrong property values after", propertyValuesBefore.intValue() - 6, propertyValuesAfter.intValue()); } + /** + * MID-6256 + */ + @Test + public void testFilterInReferences() { + UserType user = new UserType(getPrismContext()) + .linkRef("123", ShadowType.COMPLEX_TYPE); + + ObjectReferenceType reference = user.getLinkRef().get(0); + assertThat(reference.getFilter()).as("filter in simple reference").isNull(); + } } diff --git a/infra/util/src/main/java/com/evolveum/midpoint/util/DOMUtil.java b/infra/util/src/main/java/com/evolveum/midpoint/util/DOMUtil.java index 9ca6dc3eb9b..95fe3c1d770 100644 --- a/infra/util/src/main/java/com/evolveum/midpoint/util/DOMUtil.java +++ b/infra/util/src/main/java/com/evolveum/midpoint/util/DOMUtil.java @@ -1417,6 +1417,32 @@ public static void checkValidXmlChars(String stringValue) { } } + public static String escapeInvalidXmlCharsIfPresent(String value) { + if (value == null) { + return null; + } + int codepointCount = value.codePointCount(0, value.length()); + for (int i = 0; i < codepointCount; i++) { + if (!XMLChar.isValid(value.codePointAt(i))) { + return escapeInvalidXmlChars(value, codepointCount); + } + } + return value; + } + + private static String escapeInvalidXmlChars(String value, int codepointCount) { + StringBuilder sb = new StringBuilder(value.length()); + for (int i = 0; i < codepointCount; i++) { + int cp = value.codePointAt(i); + if (XMLChar.isValid(cp)) { + sb.appendCodePoint(cp); + } else { + sb.append("[INVALID CODE POINT: ").append(cp).append(']'); + } + } + return sb.toString(); + } + // todo move to some Util class private static String makeSafelyPrintable(String text, int maxSize) { StringBuilder sb = new StringBuilder(); diff --git a/infra/util/src/main/java/com/evolveum/midpoint/util/caching/AbstractThreadLocalCache.java b/infra/util/src/main/java/com/evolveum/midpoint/util/caching/AbstractThreadLocalCache.java index 995da87f35e..db454a86f4a 100644 --- a/infra/util/src/main/java/com/evolveum/midpoint/util/caching/AbstractThreadLocalCache.java +++ b/infra/util/src/main/java/com/evolveum/midpoint/util/caching/AbstractThreadLocalCache.java @@ -30,7 +30,7 @@ public static T enter(ConcurrentHashMap ResourceAttributeDefinition getAttributeDefinition(PrismObject ResourceAttributeDefinition getAttributeDefinition(PrismObject resource, String objectClassName, String attributeName) throws SchemaException; + + /** + * Goes directly to repository service. + */ + @Experimental + void createRecomputeTrigger(Class type, String oid) throws SchemaException, ObjectAlreadyExistsException, ObjectNotFoundException; } diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/util/ResourceUtils.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/util/ResourceUtils.java index 3c2917c7768..0f6ebb0f994 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/util/ResourceUtils.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/util/ResourceUtils.java @@ -16,7 +16,6 @@ import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.XmlSchemaType; -import com.evolveum.prism.xml.ns._public.types_3.SchemaDefinitionType; import static java.util.Collections.singleton; @@ -27,17 +26,13 @@ */ public class ResourceUtils { - private static final ItemPath SCHEMA_PATH = ItemPath.create(ResourceType.F_SCHEMA, XmlSchemaType.F_DEFINITION); - - public static void deleteSchema(PrismObject resource, ModelService modelService, PrismContext prismContext, Task task, OperationResult parentResult) + public static void deleteSchema(PrismObject resource, ModelService modelService, PrismContext prismContext, Task task, OperationResult parentResult) throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, PolicyViolationException, SecurityViolationException { - PrismProperty definition = resource.findProperty(SCHEMA_PATH); - if (definition != null && !definition.isEmpty()) { - ObjectDelta delta = prismContext.deltaFor(ResourceType.class) - .item(SCHEMA_PATH).replace() - .asObjectDelta(resource.getOid()); - modelService.executeChanges(singleton(delta), null, task, parentResult); - } + ObjectDelta delta = prismContext.deltaFor(ResourceType.class) + .item(ItemPath.create(ResourceType.F_SCHEMA, XmlSchemaType.F_DEFINITION)).replace() + .item(ItemPath.create(ResourceType.F_SCHEMA, XmlSchemaType.F_CACHING_METADATA)).replace() + .asObjectDelta(resource.getOid()); + modelService.executeChanges(singleton(delta), null, task, parentResult); } } diff --git a/model/model-common/pom.xml b/model/model-common/pom.xml index 9cdb91724fb..789f95e997f 100644 --- a/model/model-common/pom.xml +++ b/model/model-common/pom.xml @@ -70,11 +70,6 @@ model-api 4.2-SNAPSHOT - - com.evolveum.midpoint.repo - audit-api - 4.2-SNAPSHOT - com.evolveum.midpoint.repo repo-common @@ -120,10 +115,6 @@ org.apache.commons commons-configuration2 - - org.springframework.security - spring-security-core - org.springframework spring-context diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/FunctionExpressionEvaluatorFactory.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/FunctionExpressionEvaluatorFactory.java index 23095261f4e..d4373e5dc03 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/FunctionExpressionEvaluatorFactory.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/evaluator/FunctionExpressionEvaluatorFactory.java @@ -7,12 +7,9 @@ package com.evolveum.midpoint.model.common.expression.evaluator; import java.util.Collection; - import javax.xml.bind.JAXBElement; import javax.xml.namespace.QName; -import com.evolveum.midpoint.schema.cache.CacheConfigurationManager; -import com.evolveum.midpoint.task.api.Task; import org.apache.commons.lang.Validate; import com.evolveum.midpoint.prism.ItemDefinition; @@ -22,8 +19,10 @@ import com.evolveum.midpoint.repo.common.expression.AbstractObjectResolvableExpressionEvaluatorFactory; import com.evolveum.midpoint.repo.common.expression.ExpressionEvaluator; import com.evolveum.midpoint.repo.common.expression.ExpressionFactory; +import com.evolveum.midpoint.schema.cache.CacheConfigurationManager; import com.evolveum.midpoint.schema.expression.ExpressionProfile; import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.xml.ns._public.common.common_3.FunctionExpressionEvaluatorType; @@ -33,7 +32,6 @@ * This is NOT autowired evaluator. * * @author semancik - * */ public class FunctionExpressionEvaluatorFactory extends AbstractObjectResolvableExpressionEvaluatorFactory { @@ -42,7 +40,8 @@ public class FunctionExpressionEvaluatorFactory extends AbstractObjectResolvable private final Protector protector; private final PrismContext prismContext; - public FunctionExpressionEvaluatorFactory(ExpressionFactory expressionFactory, Protector protector, PrismContext prismContext, + public FunctionExpressionEvaluatorFactory( + ExpressionFactory expressionFactory, Protector protector, PrismContext prismContext, CacheConfigurationManager cacheConfigurationManager) { super(expressionFactory, cacheConfigurationManager); this.protector = protector; @@ -58,18 +57,18 @@ public QName getElementName() { * @see com.evolveum.midpoint.common.expression.ExpressionEvaluatorFactory#createEvaluator(javax.xml.bind.JAXBElement, com.evolveum.midpoint.prism.PrismContext) */ @Override - public ExpressionEvaluator createEvaluator( + public ExpressionEvaluator createEvaluator( Collection> evaluatorElements, D outputDefinition, ExpressionProfile expressionProfile, ExpressionFactory factory, String contextDescription, Task task, OperationResult result) - throws SchemaException, ObjectNotFoundException { + throws SchemaException, ObjectNotFoundException { Validate.notNull(outputDefinition, "output definition must be specified for 'generate' expression evaluator"); if (evaluatorElements.size() > 1) { - throw new SchemaException("More than one evaluator specified in "+contextDescription); + throw new SchemaException("More than one evaluator specified in " + contextDescription); } JAXBElement evaluatorElement = evaluatorElements.iterator().next(); @@ -78,10 +77,10 @@ public ExpressionEvaluator evaluatorTypeObject = evaluatorElement.getValue(); } if (evaluatorTypeObject != null && !(evaluatorTypeObject instanceof FunctionExpressionEvaluatorType)) { - throw new SchemaException("Function expression evaluator cannot handle elements of type " + evaluatorTypeObject.getClass().getName()+" in "+contextDescription); + throw new SchemaException("Function expression evaluator cannot handle elements of type " + evaluatorTypeObject.getClass().getName() + " in " + contextDescription); } - FunctionExpressionEvaluatorType functionEvaluatorType = (FunctionExpressionEvaluatorType)evaluatorTypeObject; + FunctionExpressionEvaluatorType functionEvaluatorType = (FunctionExpressionEvaluatorType) evaluatorTypeObject; return new FunctionExpressionEvaluator(ELEMENT_NAME, functionEvaluatorType, outputDefinition, protector, getObjectResolver(), prismContext); } diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/jsr223/Jsr223ScriptEvaluator.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/jsr223/Jsr223ScriptEvaluator.java index abec1cc65ce..eb647f1cd92 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/jsr223/Jsr223ScriptEvaluator.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/jsr223/Jsr223ScriptEvaluator.java @@ -6,79 +6,43 @@ */ package com.evolveum.midpoint.model.common.expression.script.jsr223; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Function; - -import javax.script.Bindings; -import javax.script.Compilable; -import javax.script.CompiledScript; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; -import javax.script.ScriptException; -import javax.xml.namespace.QName; +import javax.script.*; import com.evolveum.midpoint.common.LocalizationService; -import com.evolveum.midpoint.model.common.expression.functions.FunctionLibrary; import com.evolveum.midpoint.model.common.expression.script.AbstractCachingScriptEvaluator; -import com.evolveum.midpoint.model.common.expression.script.ScriptEvaluator; import com.evolveum.midpoint.model.common.expression.script.ScriptExpressionEvaluationContext; -import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.crypto.Protector; -import com.evolveum.midpoint.prism.xml.XsdTypeMapper; -import com.evolveum.midpoint.repo.common.ObjectResolver; import com.evolveum.midpoint.repo.common.expression.ExpressionSyntaxException; -import com.evolveum.midpoint.repo.common.expression.ExpressionUtil; -import com.evolveum.midpoint.repo.common.expression.ExpressionVariables; import com.evolveum.midpoint.schema.constants.MidPointConstants; -import com.evolveum.midpoint.schema.internals.InternalCounters; -import com.evolveum.midpoint.schema.internals.InternalMonitor; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.util.ExceptionUtil; -import com.evolveum.midpoint.task.api.Task; -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.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SecurityViolationException; -import com.evolveum.midpoint.util.exception.SystemException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ScriptExpressionEvaluatorType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ScriptExpressionReturnTypeType; +import com.evolveum.midpoint.util.exception.*; /** * Expression evaluator that is using javax.script (JSR-223) engine. - * + *

* This evaluator does not really support expression profiles. It has just one * global almighty compiler (ScriptEngine). * * @author Radovan Semancik - * */ -public class Jsr223ScriptEvaluator extends AbstractCachingScriptEvaluator { - - private static final Trace LOGGER = TraceManager.getTrace(Jsr223ScriptEvaluator.class); +public class Jsr223ScriptEvaluator extends AbstractCachingScriptEvaluator { private final ScriptEngine scriptEngine; - public Jsr223ScriptEvaluator(String engineName, PrismContext prismContext, Protector protector, - LocalizationService localizationService) { + public Jsr223ScriptEvaluator(String engineName, PrismContext prismContext, + Protector protector, LocalizationService localizationService) { super(prismContext, protector, localizationService); ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); scriptEngine = scriptEngineManager.getEngineByName(engineName); if (scriptEngine == null) { - throw new SystemException("The JSR-223 scripting engine for '"+engineName+"' was not found"); + throw new SystemException("The JSR-223 scripting engine for '" + engineName + "' was not found"); } } @Override protected CompiledScript compileScript(String codeString, ScriptExpressionEvaluationContext context) throws Exception { - return ((Compilable)scriptEngine).compile(codeString); + return ((Compilable) scriptEngine).compile(codeString); } @Override @@ -89,13 +53,12 @@ protected Object evaluateScript(CompiledScript compiledScript, ScriptExpressionE } private Bindings convertToBindings(ScriptExpressionEvaluationContext context) - throws ExpressionSyntaxException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException { + throws ExpressionSyntaxException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException { Bindings bindings = scriptEngine.createBindings(); bindings.putAll(prepareScriptVariablesValueMap(context)); return bindings; } - // public Object evaluateReportScript(String codeString, ScriptExpressionEvaluationContext context) throws ExpressionEvaluationException, // ObjectNotFoundException, ExpressionSyntaxException, CommunicationException, ConfigurationException, SecurityViolationException { // @@ -126,7 +89,6 @@ private Bindings convertToBindings(ScriptExpressionEvaluationContext context) // return evalRawResult; // } - /* (non-Javadoc) * @see com.evolveum.midpoint.common.expression.ExpressionEvaluator#getLanguageName() */ diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/util/AbstractModelWebService.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/util/AbstractModelWebService.java deleted file mode 100644 index f9b37f0374a..00000000000 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/util/AbstractModelWebService.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2014-2017 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.model.common.util; - -import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; - -import com.evolveum.midpoint.audit.api.AuditEventRecord; -import com.evolveum.midpoint.audit.api.AuditEventStage; -import com.evolveum.midpoint.audit.api.AuditEventType; -import com.evolveum.midpoint.audit.api.AuditService; -import com.evolveum.midpoint.model.api.ModelService; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.result.OperationResultStatus; -import com.evolveum.midpoint.security.api.MidPointPrincipal; -import com.evolveum.midpoint.security.api.SecurityContextManager; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.task.api.TaskManager; -import com.evolveum.midpoint.util.exception.SystemException; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; - -/** - * Abstract superclass that provides methods common to all web service implementations that - * use ModelService. - * - * @author Radovan Semancik - * - */ -public abstract class AbstractModelWebService { - - @Autowired protected ModelService modelService; - @Autowired protected TaskManager taskManager; - @Autowired protected AuditService auditService; - @Autowired protected PrismContext prismContext; - @Autowired protected SecurityContextManager securityContextManager; - - protected void setTaskOwner(Task task) { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication == null) { - throw new SystemException("Failed to get authentication object"); - } - FocusType focusType = ((MidPointPrincipal)(SecurityContextHolder.getContext().getAuthentication().getPrincipal())).getFocus(); - if (focusType == null) { - throw new SystemException("Failed to get user from authentication object"); - } - task.setOwner(focusType.asPrismObject()); - } - - protected Task createTaskInstance(String operationName) { - // TODO: better task initialization - Task task = taskManager.createTaskInstance(operationName); - setTaskOwner(task); - task.setChannel(SchemaConstants.CHANNEL_WEB_SERVICE_URI); - return task; - } - - protected void auditLogin(Task task) { - AuditEventRecord record = new AuditEventRecord(AuditEventType.CREATE_SESSION, AuditEventStage.REQUEST); - record.setInitiatorAndLoginParameter(task.getOwner()); - record.setChannel(SchemaConstants.CHANNEL_WEB_SERVICE_URI); - record.setTimestamp(System.currentTimeMillis()); - record.setOutcome(OperationResultStatus.SUCCESS); - auditService.audit(record, task); - } - - protected void auditLogout(Task task) { - AuditEventRecord record = new AuditEventRecord(AuditEventType.TERMINATE_SESSION, AuditEventStage.REQUEST); - record.setInitiatorAndLoginParameter(task.getOwner()); - record.setChannel(SchemaConstants.CHANNEL_WEB_SERVICE_URI); - record.setTimestamp(System.currentTimeMillis()); - record.setOutcome(OperationResultStatus.SUCCESS); - auditService.audit(record, task); - } - -} diff --git a/model/model-impl/pom.xml b/model/model-impl/pom.xml index a9033f1a2de..35c4af4d395 100644 --- a/model/model-impl/pom.xml +++ b/model/model-impl/pom.xml @@ -142,10 +142,6 @@ 4.2-SNAPSHOT - - javax.xml.soap - javax.xml.soap-api - commons-io commons-io @@ -167,12 +163,12 @@ commons-text - org.apache.cxf - cxf-core + commons-beanutils + commons-beanutils org.apache.cxf - cxf-rt-ws-security + cxf-core org.apache.cxf @@ -188,10 +184,6 @@ cxf-rt-rs-extension-providers runtime - - org.apache.cxf - cxf-rt-bindings-soap - org.apache.cxf cxf-rt-rs-client @@ -204,14 +196,6 @@ org.apache.wss4j wss4j-ws-security-common - - org.apache.wss4j - wss4j-ws-security-dom - - - org.apache.ws.xmlschema - xmlschema-core - org.jvnet.jaxb2_commons jaxb2-basics-runtime @@ -265,10 +249,6 @@ spring-boot-starter-amqp runtime - - javax.xml.ws - jaxws-api - diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelRestService.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelRestService.java index f8ed5b8c5df..cc806a89e9b 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelRestService.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelRestService.java @@ -6,31 +6,51 @@ */ package com.evolveum.midpoint.model.impl; +import java.net.URI; +import java.util.Collection; +import java.util.List; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.*; +import javax.ws.rs.core.*; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; +import javax.xml.namespace.QName; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.Validate; +import org.apache.cxf.jaxrs.ext.MessageContext; +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; + import com.evolveum.midpoint.audit.api.AuditEventRecord; import com.evolveum.midpoint.audit.api.AuditEventStage; import com.evolveum.midpoint.audit.api.AuditEventType; import com.evolveum.midpoint.audit.api.AuditService; +import com.evolveum.midpoint.common.rest.Converter; +import com.evolveum.midpoint.common.rest.ConverterInterface; import com.evolveum.midpoint.model.api.*; import com.evolveum.midpoint.model.api.validator.ResourceValidator; import com.evolveum.midpoint.model.api.validator.Scope; import com.evolveum.midpoint.model.api.validator.ValidationResult; import com.evolveum.midpoint.model.common.SystemObjectCache; -import com.evolveum.midpoint.model.common.stringpolicy.ValuePolicyProcessor; -import com.evolveum.midpoint.common.rest.Converter; -import com.evolveum.midpoint.common.rest.ConverterInterface; import com.evolveum.midpoint.model.impl.rest.PATCH; +import com.evolveum.midpoint.model.impl.scripting.PipelineData; import com.evolveum.midpoint.model.impl.scripting.ScriptingExpressionEvaluator; import com.evolveum.midpoint.model.impl.security.SecurityHelper; import com.evolveum.midpoint.model.impl.util.RestServiceUtil; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.crypto.Protector; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.ItemPathCollectionsUtil; import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.repo.api.CacheDispatcher; -import com.evolveum.midpoint.schema.*; +import com.evolveum.midpoint.schema.DefinitionProcessingOption; +import com.evolveum.midpoint.schema.DeltaConvertor; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.constants.MidPointConstants; import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.constants.SchemaConstants; @@ -53,31 +73,12 @@ import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ScriptingExpressionType; import com.evolveum.prism.xml.ns._public.query_3.QueryType; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang.Validate; -import org.apache.cxf.jaxrs.ext.MessageContext; -import org.jetbrains.annotations.NotNull; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Service; - -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.*; -import javax.ws.rs.core.*; -import javax.ws.rs.core.Response.ResponseBuilder; -import javax.ws.rs.core.Response.Status; -import javax.xml.namespace.QName; -import java.net.URI; -import java.util.Collection; -import java.util.List; - /** * @author katkav * @author semancik */ @Service -@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) +@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) public class ModelRestService { public static final String CLASS_DOT = ModelRestService.class.getName() + "."; @@ -102,10 +103,10 @@ public class ModelRestService { public static final String OPERATION_COMPARE = CLASS_DOT + "compare"; public static final String OPERATION_GET_LOG_FILE_CONTENT = CLASS_DOT + "getLogFileContent"; public static final String OPERATION_GET_LOG_FILE_SIZE = CLASS_DOT + "getLogFileSize"; - public static final String OPERATION_VALIDATE_VALUE = CLASS_DOT + "validateValue"; - public static final String OPERATION_VALIDATE_VALUE_RPC = CLASS_DOT + "validateValueRpc"; - public static final String OPERATION_GENERATE_VALUE = CLASS_DOT + "generateValue"; - public static final String OPERATION_GENERATE_VALUE_RPC = CLASS_DOT + "generateValueRpc"; + public static final String OPERATION_VALIDATE_VALUE = CLASS_DOT + "validateValue"; + public static final String OPERATION_VALIDATE_VALUE_RPC = CLASS_DOT + "validateValueRpc"; + public static final String OPERATION_GENERATE_VALUE = CLASS_DOT + "generateValue"; + public static final String OPERATION_GENERATE_VALUE_RPC = CLASS_DOT + "generateValueRpc"; public static final String OPERATION_EXECUTE_CREDENTIAL_RESET = CLASS_DOT + "executeCredentialReset"; public static final String OPERATION_EXECUTE_CLUSTER_EVENT = CLASS_DOT + "executeClusterCacheInvalidationEvent"; public static final String OPERATION_GET_LOCAL_SCHEDULER_INFORMATION = CLASS_DOT + "getLocalSchedulerInformation"; @@ -126,14 +127,10 @@ public class ModelRestService { @Autowired private ModelInteractionService modelInteraction; @Autowired private PrismContext prismContext; @Autowired private SecurityHelper securityHelper; - @Autowired private ValuePolicyProcessor policyProcessor; @Autowired private TaskManager taskManager; @Autowired private TaskService taskService; - @Autowired private Protector protector; @Autowired private ResourceValidator resourceValidator; - @Autowired private CacheDispatcher cacheDispatcher; - @Autowired private SystemObjectCache systemObjectCache; @Autowired private AuditService auditService; @@ -147,8 +144,8 @@ public ModelRestService() { @POST @Path("/{type}/{oid}/generate") - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) - @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) public Response generateValue(@PathParam("type") String type, @PathParam("oid") String oid, PolicyItemsDefinitionType policyItemsDefinition, @Context MessageContext mc) { @@ -174,8 +171,8 @@ public Response generateValue(@PathParam("type") String type, @POST @Path("/rpc/generate") - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) - @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) public Response generateValue(PolicyItemsDefinitionType policyItemsDefinition, @Context MessageContext mc) { @@ -188,7 +185,7 @@ public Response generateValue(PolicyItemsDefinitionType policyItemsDefinition, return response; } - private Response generateValue(PrismObject object, PolicyItemsDefinitionType policyItemsDefinition, Task task, OperationResult parentResult){ + private Response generateValue(PrismObject object, PolicyItemsDefinitionType policyItemsDefinition, Task task, OperationResult parentResult) { Response response; if (policyItemsDefinition == null) { response = createBadPolicyItemsDefinitionResponse("Policy items definition must not be null", parentResult); @@ -212,8 +209,8 @@ private Response generateValue(PrismObject object, Pol @POST @Path("/{type}/{oid}/validate") - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) - @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) public Response validateValue(@PathParam("type") String type, @PathParam("oid") String oid, PolicyItemsDefinitionType policyItemsDefinition, @Context MessageContext mc) { Task task = initRequest(mc); @@ -235,8 +232,8 @@ public Response validateValue(@PathParam("type") String type, @PathParam("oid") @POST @Path("/rpc/validate") - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) - @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) public Response validateValue(PolicyItemsDefinitionType policyItemsDefinition, @Context MessageContext mc) { Task task = initRequest(mc); @@ -263,24 +260,22 @@ private Response validateValue(PrismObject object, Htt return response; } + try { + modelInteraction.validateValue(object, policyItemsDefinition, task, parentResult); - try { - modelInteraction.validateValue(object, policyItemsDefinition, task, parentResult); - - parentResult.computeStatusIfUnknown(); - ResponseBuilder responseBuilder; - if (parentResult.isAcceptable()) { - response = RestServiceUtil.createResponse(Response.Status.OK, policyItemsDefinition, parentResult, true); - } else { - responseBuilder = Response.status(Status.CONFLICT).entity(parentResult); - response = responseBuilder.build(); - } - - } catch (Exception ex) { - parentResult.computeStatus(); - response = RestServiceUtil.handleException(parentResult, ex); + parentResult.computeStatusIfUnknown(); + ResponseBuilder responseBuilder; + if (parentResult.isAcceptable()) { + response = RestServiceUtil.createResponse(Response.Status.OK, policyItemsDefinition, parentResult, true); + } else { + responseBuilder = Response.status(Status.CONFLICT).entity(parentResult); + response = responseBuilder.build(); } + } catch (Exception ex) { + parentResult.computeStatus(); + response = RestServiceUtil.handleException(parentResult, ex); + } return response; } @@ -323,13 +318,13 @@ public Response getValuePolicyForUser(@PathParam("id") String oid, @Context Mess @GET @Path("/{type}/{id}") - @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) public Response getObject(@PathParam("type") String type, @PathParam("id") String id, @QueryParam("options") List options, @QueryParam("include") List include, @QueryParam("exclude") List exclude, @QueryParam("resolveNames") List resolveNames, - @Context MessageContext mc){ + @Context MessageContext mc) { LOGGER.debug("model rest service for get operation start"); Task task = initRequest(mc); @@ -347,7 +342,7 @@ public Response getObject(@PathParam("type") String type, @PathParam("id") Strin ObjectQuery query = prismContext.queryFor(NodeType.class) .item(NodeType.F_NODE_IDENTIFIER).eq(nodeId) .build(); - List> objects = model.searchObjects(NodeType.class, query, getOptions, task, parentResult); + List> objects = model.searchObjects(NodeType.class, query, getOptions, task, parentResult); if (objects.isEmpty()) { throw new ObjectNotFoundException("Current node (id " + nodeId + ") couldn't be found."); } else if (objects.size() > 1) { @@ -372,8 +367,8 @@ public Response getObject(@PathParam("type") String type, @PathParam("id") Strin @GET @Path("/self") - @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) - public Response getSelf(@Context MessageContext mc){ + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) + public Response getSelf(@Context MessageContext mc) { LOGGER.debug("model rest service for get operation start"); Task task = initRequest(mc); @@ -394,12 +389,11 @@ public Response getSelf(@Context MessageContext mc){ return response; } - @POST @Path("/{type}") - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) public Response addObject(@PathParam("type") String type, PrismObject object, - @QueryParam("options") List options, + @QueryParam("options") List options, @Context UriInfo uriInfo, @Context MessageContext mc) { LOGGER.debug("model rest service for add operation start"); @@ -407,7 +401,7 @@ public Response addObject(@PathParam("type") String type, OperationResult parentResult = task.getResult().createSubresult(OPERATION_ADD_OBJECT); Class clazz = ObjectTypes.getClassFromRestType(type); - if (!object.getCompileTimeClass().equals(clazz)){ + if (!object.getCompileTimeClass().equals(clazz)) { finishRequest(task, mc.getHttpServletRequest()); parentResult.recordFatalError("Request to add object of type " + object.getCompileTimeClass().getSimpleName() + " to the collection of " + type); @@ -420,7 +414,7 @@ public Response addObject(@PathParam("type") String type, Response response; try { oid = model.addObject(object, modelExecuteOptions, task, parentResult); - LOGGER.debug("returned oid : {}", oid ); + LOGGER.debug("returned oid : {}", oid); if (oid != null) { URI resourceURI = uriInfo.getAbsolutePathBuilder().path(oid).build(oid); @@ -441,7 +435,7 @@ public Response addObject(@PathParam("type") String type, @GET @Path("/{type}") - @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) public Response searchObjectsByType(@PathParam("type") String type, @QueryParam("options") List options, @QueryParam("include") List include, @QueryParam("exclude") List exclude, @QueryParam("resolveNames") List resolveNames, @@ -487,10 +481,10 @@ private void validateIfRequested(PrismObject object, @PUT @Path("/{type}/{id}") - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) public Response addObject(@PathParam("type") String type, @PathParam("id") String id, PrismObject object, @QueryParam("options") List options, @Context UriInfo uriInfo, - @Context Request request, @Context MessageContext mc){ + @Context Request request, @Context MessageContext mc) { LOGGER.debug("model rest service for add operation start"); @@ -498,7 +492,7 @@ public Response addObject(@PathParam("type") String type, OperationResult parentResult = task.getResult().createSubresult(OPERATION_ADD_OBJECT); Class clazz = ObjectTypes.getClassFromRestType(type); - if (!object.getCompileTimeClass().equals(clazz)){ + if (!object.getCompileTimeClass().equals(clazz)) { finishRequest(task, mc.getHttpServletRequest()); parentResult.recordFatalError("Request to add object of type " + object.getCompileTimeClass().getSimpleName() @@ -509,7 +503,7 @@ public Response addObject(@PathParam("type") String type, ModelExecuteOptions modelExecuteOptions = ModelExecuteOptions.fromRestOptions(options); if (modelExecuteOptions == null) { modelExecuteOptions = ModelExecuteOptions.createOverwrite(); - } else if (!ModelExecuteOptions.isOverwrite(modelExecuteOptions)){ + } else if (!ModelExecuteOptions.isOverwrite(modelExecuteOptions)) { modelExecuteOptions.setOverwrite(Boolean.TRUE); } @@ -534,7 +528,7 @@ public Response addObject(@PathParam("type") String type, @DELETE @Path("/{type}/{id}") public Response deleteObject(@PathParam("type") String type, @PathParam("id") String id, - @QueryParam("options") List options, @Context MessageContext mc){ + @QueryParam("options") List options, @Context MessageContext mc) { LOGGER.debug("model rest service for delete operation start"); @@ -569,7 +563,7 @@ public Response deleteObject(@PathParam("type") String type, @PathParam("id") St @POST @Path("/{type}/{oid}") - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) public Response modifyObjectPost(@PathParam("type") String type, @PathParam("oid") String oid, ObjectModificationType modificationType, @QueryParam("options") List options, @Context MessageContext mc) { return modifyObjectPatch(type, oid, modificationType, options, mc); @@ -577,7 +571,7 @@ public Response modifyObjectPost(@PathParam("type") String type, @PathParam("oid @PATCH @Path("/{type}/{oid}") - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) public Response modifyObjectPatch(@PathParam("type") String type, @PathParam("oid") String oid, ObjectModificationType modificationType, @QueryParam("options") List options, @Context MessageContext mc) { @@ -605,7 +599,7 @@ public Response modifyObjectPatch(@PathParam("type") String type, @PathParam("oi @POST @Path("/notifyChange") - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) public Response notifyChange(ResourceObjectShadowChangeDescriptionType changeDescription, @Context UriInfo uriInfo, @Context MessageContext mc) { LOGGER.debug("model rest service for notify change operation start"); @@ -629,8 +623,8 @@ public Response notifyChange(ResourceObjectShadowChangeDescriptionType changeDes @GET @Path("/shadows/{oid}/owner") - @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) - public Response findShadowOwner(@PathParam("oid") String shadowOid, @Context MessageContext mc){ + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) + public Response findShadowOwner(@PathParam("oid") String shadowOid, @Context MessageContext mc) { Task task = initRequest(mc); OperationResult parentResult = task.getResult().createSubresult(OPERATION_FIND_SHADOW_OWNER); @@ -650,7 +644,7 @@ public Response findShadowOwner(@PathParam("oid") String shadowOid, @Context Mes @POST @Path("/shadows/{oid}/import") - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) public Response importShadow(@PathParam("oid") String shadowOid, @Context MessageContext mc, @Context UriInfo uriInfo) { LOGGER.debug("model rest service for import shadow from resource operation start"); @@ -673,8 +667,8 @@ public Response importShadow(@PathParam("oid") String shadowOid, @Context Messag @POST @Path("/{type}/search") - @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) public Response searchObjects(@PathParam("type") String type, QueryType queryType, @QueryParam("options") List options, @QueryParam("include") List include, @@ -716,7 +710,7 @@ private void removeExcludes(PrismObject object, List Response compare(PrismObject clientObject, @QueryParam("readOptions") List restReadOptions, @QueryParam("compareOptions") List restCompareOptions, @@ -904,7 +900,7 @@ public Response compare(PrismObject clientObject, @GET @Path("/log/size") - @Produces({"text/plain"}) + @Produces({ "text/plain" }) public Response getLogFileSize(@Context MessageContext mc) { Task task = initRequest(mc); @@ -926,7 +922,7 @@ public Response getLogFileSize(@Context MessageContext mc) { @GET @Path("/log") - @Produces({"text/plain"}) + @Produces({ "text/plain" }) public Response getLog(@QueryParam("fromPosition") Long fromPosition, @QueryParam("maxSize") Long maxSize, @Context MessageContext mc) { Task task = initRequest(mc); @@ -956,8 +952,8 @@ public Response getLog(@QueryParam("fromPosition") Long fromPosition, @QueryPara @POST @Path("/users/{oid}/credential") - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) - @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML}) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, RestServiceUtil.APPLICATION_YAML }) public Response executeCredentialReset(@PathParam("oid") String oid, ExecuteCredentialResetRequestType executeCredentialResetRequest, @Context MessageContext mc) { Task task = initRequest(mc); OperationResult result = task.getResult().createSubresult(OPERATION_EXECUTE_CREDENTIAL_RESET); @@ -976,12 +972,11 @@ public Response executeCredentialReset(@PathParam("oid") String oid, ExecuteCred finishRequest(task, mc.getHttpServletRequest()); return response; - } @GET @Path("/threads") - @Produces({"text/plain"}) + @Produces({ "text/plain" }) public Response getThreadsDump(@Context MessageContext mc) { Task task = initRequest(mc); @@ -1002,7 +997,7 @@ public Response getThreadsDump(@Context MessageContext mc) { @GET @Path("/tasks/threads") - @Produces({"text/plain"}) + @Produces({ "text/plain" }) public Response getRunningTasksThreadsDump(@Context MessageContext mc) { Task task = initRequest(mc); @@ -1023,7 +1018,7 @@ public Response getRunningTasksThreadsDump(@Context MessageContext mc) { @GET @Path("/tasks/{oid}/threads") - @Produces({"text/plain"}) + @Produces({ "text/plain" }) public Response getTaskThreadsDump(@PathParam("oid") String oid, @Context MessageContext mc) { Task task = initRequest(mc); OperationResult result = task.getResult().createSubresult(OPERATION_GET_TASK_THREADS_DUMP); @@ -1075,10 +1070,10 @@ public void auditEvent(HttpServletRequest request) { String name = null; if (principal instanceof MidPointPrincipal) { name = ((MidPointPrincipal) principal).getUsername(); - } else if (principal != null){ + } else if (principal != null) { return; } - PrismObject user = principal!= null ? ((MidPointPrincipal)principal).getFocus().asPrismObject() : null; + PrismObject user = principal != null ? ((MidPointPrincipal) principal).getFocus().asPrismObject() : null; Task task = taskManager.createTaskInstance(); task.setOwner(user); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelWebService.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelWebService.java deleted file mode 100644 index cecb25e7720..00000000000 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelWebService.java +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (c) 2010-2017 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.model.impl; - -import com.evolveum.midpoint.model.api.*; -import com.evolveum.midpoint.model.common.util.AbstractModelWebService; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismProperty; -import com.evolveum.midpoint.prism.PrismReferenceValue; -import com.evolveum.midpoint.prism.PrismValue; -import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.schema.DeltaConvertor; -import com.evolveum.midpoint.schema.GetOperationOptions; -import com.evolveum.midpoint.schema.ObjectDeltaOperation; -import com.evolveum.midpoint.schema.SelectorOptions; -import com.evolveum.midpoint.schema.constants.ObjectTypes; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -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.util.exception.*; -import com.evolveum.midpoint.util.logging.LoggingUtils; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.api_types_3.*; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import com.evolveum.midpoint.xml.ns._public.common.fault_3.*; -import com.evolveum.midpoint.xml.ns._public.model.model_3.ExecuteScriptsResponseType; -import com.evolveum.midpoint.xml.ns._public.model.model_3.ExecuteScriptsType; -import com.evolveum.midpoint.xml.ns._public.model.model_3.ModelPortType; -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.PipelineDataType; -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.PipelineItemType; -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ScriptingExpressionEvaluationOptionsType; -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ScriptingExpressionType; -import com.evolveum.prism.xml.ns._public.query_3.QueryType; -import org.apache.commons.lang.StringUtils; -import org.apache.cxf.interceptor.Fault; -import org.apache.wss4j.common.ext.WSSecurityException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.namespace.QName; -import javax.xml.ws.Holder; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * - * @author lazyman - * - */ -@Service -public class ModelWebService extends AbstractModelWebService implements ModelPortType, ModelPort { - - private static final Trace LOGGER = TraceManager.getTrace(ModelWebService.class); - - @Autowired(required = true) - private ModelCrudService model; - - @Autowired - private ScriptingService scriptingService; - - @Override - public void getObject(QName objectType, String oid, SelectorQualifiedGetOptionsType optionsType, - Holder objectHolder, Holder resultHolder) throws FaultMessage { - notNullArgument(objectType, "Object type must not be null."); - notEmptyArgument(oid, "Oid must not be null or empty."); - - Task task = createTaskInstance(GET_OBJECT); - auditLogin(task); - OperationResult operationResult = task.getResult(); - try { - Class objectClass = ObjectTypes.getObjectTypeFromTypeQName(objectType).getClassDefinition(); - Collection> options = MiscSchemaUtil.optionsTypeToOptions(optionsType, - prismContext); - PrismObject object = model.getObject(objectClass, oid, options, task, operationResult); - handleOperationResult(operationResult, resultHolder); - objectHolder.value = object.asObjectable(); - return; - } catch (Exception ex) { - LoggingUtils.logException(LOGGER, "# MODEL getObject() failed", ex); - throwFault(ex, operationResult); - } finally { - auditLogout(task); - } - } - - @Override - public void searchObjects(QName objectType, QueryType query, SelectorQualifiedGetOptionsType optionsType, - Holder objectListHolder, Holder result) throws FaultMessage { - notNullArgument(objectType, "Object type must not be null."); - - Task task = createTaskInstance(SEARCH_OBJECTS); - auditLogin(task); - OperationResult operationResult = task.getResult(); - try { - Class objectClass = ObjectTypes.getObjectTypeFromTypeQName(objectType).getClassDefinition(); - Collection> options = MiscSchemaUtil.optionsTypeToOptions(optionsType, - prismContext); - ObjectQuery q = prismContext.getQueryConverter().createObjectQuery(objectClass, query); - List> list = (List)model.searchObjects(objectClass, q, options, task, operationResult); - handleOperationResult(operationResult, result); - ObjectListType listType = new ObjectListType(); - for (PrismObject o : list) { - listType.getObject().add(o.asObjectable()); - } - objectListHolder.value = listType; - } catch (Exception ex) { - LoggingUtils.logException(LOGGER, "# MODEL searchObjects() failed", ex); - throwFault(ex, operationResult); - } finally { - auditLogout(task); - } - } - - @Override - public ObjectDeltaOperationListType executeChanges(ObjectDeltaListType deltaList, ModelExecuteOptionsType optionsType) throws FaultMessage { - notNullArgument(deltaList, "Object delta list must not be null."); - - Task task = createTaskInstance(EXECUTE_CHANGES); - auditLogin(task); - OperationResult operationResult = task.getResult(); - try { - Collection deltas = DeltaConvertor.createObjectDeltas(deltaList, prismContext); - for (ObjectDelta delta : deltas) { - prismContext.adopt(delta); - } - ModelExecuteOptions options = ModelExecuteOptions.fromModelExecutionOptionsType(optionsType); - Collection> objectDeltaOperations = modelService.executeChanges((Collection) deltas, options, task, operationResult); // brutally eliminating type-safety compiler barking - ObjectDeltaOperationListType retval = new ObjectDeltaOperationListType(); - for (ObjectDeltaOperation objectDeltaOperation : objectDeltaOperations) { - ObjectDeltaOperationType objectDeltaOperationType = DeltaConvertor.toObjectDeltaOperationType(objectDeltaOperation, null); - retval.getDeltaOperation().add(objectDeltaOperationType); - } - return retval; - } catch (Exception ex) { - LoggingUtils.logException(LOGGER, "# MODEL executeChanges() failed", ex); - throwFault(ex, operationResult); - // notreached - return null; - } finally { - auditLogout(task); - } - } - - @Override - public void findShadowOwner(String accountOid, Holder userHolder, Holder result) - throws FaultMessage { - notEmptyArgument(accountOid, "Account oid must not be null or empty."); - - Task task = createTaskInstance(LIST_ACCOUNT_SHADOW_OWNER); - auditLogin(task); - OperationResult operationResult = task.getResult(); - try { - PrismObject user = modelService.searchShadowOwner(accountOid, null, task, operationResult); - handleOperationResult(operationResult, result); - if (user != null && user.asObjectable() instanceof UserType) { - // The schema for findShadowOwner SOAP call requires the returned object is of UserType. - // SOAP interface will be removed anyway, so let's not try to resolve this more intelligently. - userHolder.value = (UserType) user.asObjectable(); - } - return; - } catch (Exception ex) { - LoggingUtils.logException(LOGGER, "# MODEL findShadowOwner() failed", ex); - throwFault(ex, operationResult); - } finally { - auditLogout(task); - } - } - - @Override - public OperationResultType testResource(String resourceOid) throws FaultMessage { - notEmptyArgument(resourceOid, "Resource oid must not be null or empty."); - - Task task = createTaskInstance(TEST_RESOURCE); - auditLogin(task); - try { - OperationResult testResult = modelService.testResource(resourceOid, task); - return handleOperationResult(testResult); - } catch (Exception ex) { - LoggingUtils.logException(LOGGER, "# MODEL testResource() failed", ex); - OperationResult faultResult = new OperationResult(TEST_RESOURCE); - faultResult.recordFatalError(ex); - throwFault(ex, faultResult); - // notreached - return null; - } finally { - auditLogout(task); - } - } - - @Override - public ExecuteScriptsResponseType executeScripts(ExecuteScriptsType parameters) throws FaultMessage { - Task task = createTaskInstance(EXECUTE_SCRIPTS); - auditLogin(task); - OperationResult result = task.getResult(); - try { - List> scriptsToExecute = parseScripts(parameters); - return doExecuteScripts(scriptsToExecute, parameters.getOptions(), task, result); - } catch (Exception ex) { - LoggingUtils.logException(LOGGER, "# MODEL executeScripts() failed", ex); - throwFault(ex, null); - // notreached - return null; - } finally { - auditLogout(task); - } - } - - private List> parseScripts(ExecuteScriptsType parameters) throws JAXBException, SchemaException { - List> scriptsToExecute = new ArrayList<>(); - if (parameters.getXmlScripts() != null) { - for (Object scriptAsObject : parameters.getXmlScripts().getAny()) { - if (scriptAsObject instanceof JAXBElement) { - scriptsToExecute.add((JAXBElement) scriptAsObject); - } else { - throw new IllegalArgumentException("Invalid script type: " + scriptAsObject.getClass()); - } - } - } else { - // here comes MSL script decoding (however with a quick hack to allow passing XML as text here) - String scriptsAsString = parameters.getMslScripts(); - if (scriptsAsString.startsWith(" expressionType = (PrismProperty) prismContext.parserFor(scriptsAsString).xml().parseItem(); - if (expressionType.size() != 1) { - throw new IllegalArgumentException("Unexpected number of scripting expressions at input: " + expressionType.size() + " (expected 1)"); - } - scriptsToExecute.add(expressionType.getAnyValue().toJaxbElement()); - } - } - return scriptsToExecute; - } - - private ExecuteScriptsResponseType doExecuteScripts(List> scriptsToExecute, ExecuteScriptsOptionsType options, Task task, OperationResult result) { - ExecuteScriptsResponseType response = new ExecuteScriptsResponseType(); - ScriptOutputsType outputs = new ScriptOutputsType(); - response.setOutputs(outputs); - - try { - for (JAXBElement script : scriptsToExecute) { - - Object scriptValue = script.getValue(); - if (!(scriptValue instanceof ScriptingExpressionType)) { - throw new SchemaException("Expected that scripts will be of type ScriptingExpressionType, but it was "+scriptValue.getClass().getName()); - } - - ScriptExecutionResult executionResult = scriptingService.evaluateExpression((ScriptingExpressionType) script.getValue(), task, result); - - SingleScriptOutputType output = new SingleScriptOutputType(); - outputs.getOutput().add(output); - - output.setTextOutput(executionResult.getConsoleOutput()); - if (options == null || options.getOutputFormat() == null || options.getOutputFormat() == OutputFormatType.XML) { - output.setDataOutput(prepareXmlData(executionResult.getDataOutput(), null)); - } else { - // temporarily we send serialized XML in the case of MSL output - PipelineDataType jaxbOutput = prepareXmlData(executionResult.getDataOutput(), null); - output.setMslData(prismContext.xmlSerializer().serializeAnyData(jaxbOutput, SchemaConstants.C_VALUE)); - } - } - result.computeStatusIfUnknown(); - } catch (ScriptExecutionException | JAXBException | SchemaException | RuntimeException | SecurityViolationException | ObjectNotFoundException | ExpressionEvaluationException | CommunicationException | ConfigurationException e) { - result.recordFatalError(e.getMessage(), e); - LoggingUtils.logException(LOGGER, "Exception while executing script", e); - } - result.summarize(); - response.setResult(result.createOperationResultType()); - return response; - } - - public static PipelineDataType prepareXmlData(List output, - ScriptingExpressionEvaluationOptionsType options) throws JAXBException, SchemaException { - boolean hideResults = options != null && Boolean.TRUE.equals(options.isHideOperationResults()); - PipelineDataType rv = new PipelineDataType(); - if (output != null) { - for (PipelineItem item: output) { - PipelineItemType itemType = new PipelineItemType(); - PrismValue value = item.getValue(); - if (value instanceof PrismReferenceValue) { - // This is a bit of hack: value.getRealValue() would return unserializable object (PRV$1 - does not have type QName) - ObjectReferenceType ort = new ObjectReferenceType(); - ort.setupReferenceValue((PrismReferenceValue) value); - itemType.setValue(ort); - } else { - itemType.setValue(value.getRealValue()); // TODO - ok? - } - if (!hideResults) { - itemType.setResult(item.getResult().createOperationResultType()); - } - rv.getItem().add(itemType); - } - } - return rv; - } - - private void handleOperationResult(OperationResult result, Holder holder) { - result.recordSuccess(); - OperationResultType resultType = result.createOperationResultType(); - if (holder.value == null) { - holder.value = resultType; - } else { - holder.value.getPartialResults().add(resultType); - } - } - - private OperationResultType handleOperationResult(OperationResult result) { - result.recordSuccess(); - return result.createOperationResultType(); - } - - private void notNullResultHolder(Holder holder) throws FaultMessage { - notNullArgument(holder, "Holder must not be null."); - notNullArgument(holder.value, "Result type must not be null."); - } - - private void notNullHolder(Holder holder) throws FaultMessage { - notNullArgument(holder, "Holder must not be null."); - notNullArgument(holder.value, holder.getClass().getSimpleName() + " must not be null (in Holder)."); - } - - private void notEmptyArgument(String object, String message) throws FaultMessage { - if (StringUtils.isEmpty(object)) { - throw createIllegalArgumentFault(message); - } - } - - private void notNullArgument(Object object, String message) throws FaultMessage { - if (object == null) { - throw createIllegalArgumentFault(message); - } - } - - public FaultMessage createIllegalArgumentFault(String message) { - FaultType faultType = new IllegalArgumentFaultType(); - return new FaultMessage(message, faultType); - } - - public void throwFault(Throwable ex, OperationResult result) throws FaultMessage { - if (result != null) { - result.recordFatalError(ex.getMessage(), ex); - } - - FaultType faultType; - if (ex instanceof ObjectNotFoundException) { - faultType = new ObjectNotFoundFaultType(); - } else if (ex instanceof IllegalArgumentException) { - faultType = new IllegalArgumentFaultType(); - } else if (ex instanceof ObjectAlreadyExistsException) { - faultType = new ObjectAlreadyExistsFaultType(); - } else if (ex instanceof CommunicationException) { - faultType = new CommunicationFaultType(); - } else if (ex instanceof ConfigurationException) { - faultType = new ConfigurationFaultType(); - } else if (ex instanceof ExpressionEvaluationException) { - faultType = new SystemFaultType(); - } else if (ex instanceof SchemaException) { - faultType = new SchemaViolationFaultType(); - } else if (ex instanceof PolicyViolationException) { - faultType = new PolicyViolationFaultType(); - } else if (ex instanceof AuthorizationException) { - throw new Fault(new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION), - WSSecurityException.ErrorCode.FAILED_AUTHENTICATION.getQName()); - } else if (ex instanceof SecurityViolationException) { - throw new Fault(new WSSecurityException(WSSecurityException.ErrorCode.FAILURE), - WSSecurityException.ErrorCode.FAILURE.getQName()); - } else{ - faultType = new SystemFaultType(); - } - faultType.setMessage(ex.getMessage()); - if (result != null) { - faultType.setOperationResult(result.createOperationResultType()); - } - - FaultMessage fault = new FaultMessage(ex.getMessage(), faultType, ex); - LOGGER.trace("Throwing fault message type: {}", faultType.getClass(), fault); - throw fault; - } - - @Override - public TaskType importFromResource(String resourceOid, QName objectClass) - throws FaultMessage { - notEmptyArgument(resourceOid, "Resource oid must not be null or empty."); - notNullArgument(objectClass, "Object class must not be null."); - - Task task = createTaskInstance(IMPORT_FROM_RESOURCE); - auditLogin(task); - OperationResult operationResult = task.getResult(); - - try { - modelService.importFromResource(resourceOid, objectClass, task, operationResult); - operationResult.computeStatus(); - return handleTaskResult(task); - } catch (Exception ex) { - LoggingUtils.logException(LOGGER, "# MODEL importFromResource() failed", ex); - auditLogout(task); - throwFault(ex, operationResult); - // notreached - return null; - } - } - - @Override - public TaskType notifyChange(ResourceObjectShadowChangeDescriptionType changeDescription) - throws FaultMessage { - // TODO Auto-generated method stub - notNullArgument(changeDescription, "Change description must not be null"); - LOGGER.trace("notify change started"); - - Task task = createTaskInstance(NOTIFY_CHANGE); - OperationResult parentResult = task.getResult(); - - try { - modelService.notifyChange(changeDescription, task, parentResult); - } catch (ObjectNotFoundException | SchemaException | CommunicationException | ConfigurationException | - SecurityViolationException | ObjectAlreadyExistsException | ExpressionEvaluationException | - RuntimeException | Error | PolicyViolationException ex) { - LoggingUtils.logException(LOGGER, "# MODEL notifyChange() failed", ex); - auditLogout(task); - throwFault(ex, parentResult); - } - - - LOGGER.info("notify change ended."); - LOGGER.info("result of notify change: {}", parentResult.debugDump()); - return handleTaskResult(task); - } - - /** - * return appropriate form of taskType (and result) to - * return back to a web service caller. - * - * @param task - */ - private TaskType handleTaskResult(Task task) { - return task.getUpdatedTaskObject().asObjectable(); - } - -} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelWebServiceRaw.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelWebServiceRaw.java deleted file mode 100644 index 80bfeb1fc4b..00000000000 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ModelWebServiceRaw.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2010-2015 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.model.impl; - -import com.evolveum.midpoint.model.api.ModelPort; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismSerializer; -import com.evolveum.midpoint.prism.SerializationOptions; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectDeltaOperationListType; -import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectListType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -import com.evolveum.midpoint.xml.ns._public.common.fault_3.FaultMessage; -import com.evolveum.midpoint.xml.ns._public.model.model_3.ExecuteChangesResponseType; -import com.evolveum.midpoint.xml.ns._public.model.model_3.ExecuteChangesType; -import com.evolveum.midpoint.xml.ns._public.model.model_3.ExecuteScriptsResponseType; -import com.evolveum.midpoint.xml.ns._public.model.model_3.ExecuteScriptsType; -import com.evolveum.midpoint.xml.ns._public.model.model_3.FindShadowOwnerResponseType; -import com.evolveum.midpoint.xml.ns._public.model.model_3.FindShadowOwnerType; -import com.evolveum.midpoint.xml.ns._public.model.model_3.GetObjectResponseType; -import com.evolveum.midpoint.xml.ns._public.model.model_3.GetObjectType; -import com.evolveum.midpoint.xml.ns._public.model.model_3.ImportFromResourceResponseType; -import com.evolveum.midpoint.xml.ns._public.model.model_3.ImportFromResourceType; -import com.evolveum.midpoint.xml.ns._public.model.model_3.NotifyChangeResponseType; -import com.evolveum.midpoint.xml.ns._public.model.model_3.NotifyChangeType; -import com.evolveum.midpoint.xml.ns._public.model.model_3.SearchObjectsResponseType; -import com.evolveum.midpoint.xml.ns._public.model.model_3.SearchObjectsType; -import com.evolveum.midpoint.xml.ns._public.model.model_3.TestResourceResponseType; -import com.evolveum.midpoint.xml.ns._public.model.model_3.TestResourceType; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import javax.xml.namespace.QName; -import javax.xml.soap.Detail; -import javax.xml.soap.SOAPException; -import javax.xml.soap.SOAPFactory; -import javax.xml.soap.SOAPFault; -import javax.xml.transform.dom.DOMSource; -import javax.xml.ws.Holder; -import javax.xml.ws.Provider; -import javax.xml.ws.soap.SOAPFaultException; - -/** - * - * @author mederly - * - */ -@Service -public class ModelWebServiceRaw implements Provider { - - private static final Trace LOGGER = TraceManager.getTrace(ModelWebServiceRaw.class); - - public static final String NS_SOAP11_ENV = "http://schemas.xmlsoap.org/soap/envelope/"; - public static final String NS_SOAP11_ENV_PREFIX = "SOAP-ENV"; - public static final QName SOAP11_FAULT = new QName(NS_SOAP11_ENV, "Fault"); - public static final QName SOAP11_FAULTCODE = new QName("", "faultcode"); - public static final String SOAP11_FAULTCODE_SERVER = NS_SOAP11_ENV_PREFIX + ":Server"; - public static final QName SOAP11_FAULTSTRING = new QName("", "faultstring"); - public static final QName SOAP11_FAULTACTOR = new QName("", "faultactor"); - public static final QName SOAP11_FAULT_DETAIL = new QName("", "detail"); - public static final String ACTOR = "TODO"; - - @Autowired - private ModelWebService ws; - - @Autowired - private PrismContext prismContext; - - @Override - public DOMSource invoke(DOMSource request) { - try { - return invokeAllowingFaults(request); - } catch (FaultMessage faultMessage) { - try { - SOAPFactory factory = SOAPFactory.newInstance(); - SOAPFault soapFault = factory.createFault(); - soapFault.setFaultCode(SOAP11_FAULTCODE_SERVER); // todo here is a constant until we have a mechanism to determine the correct value (client / server) - soapFault.setFaultString(faultMessage.getMessage()); - Detail detail = soapFault.addDetail(); - serializeFaultMessage(detail, faultMessage); - // fault actor? - // stack trace of the outer exception (FaultMessage) is unimportant, because it is always created at one place - // todo consider providing stack trace of the inner exception - //Detail detail = soapFault.addDetail(); - //detail.setTextContent(getStackTraceAsString(faultMessage)); - throw new SOAPFaultException(soapFault); - } catch (SOAPException e) { - throw new RuntimeException("SOAP Exception: " + e.getMessage(), e); - } - } - } - - public DOMSource invokeAllowingFaults(DOMSource request) throws FaultMessage { - Node rootNode = request.getNode(); - Element rootElement; - if (rootNode instanceof Document) { - rootElement = ((Document) rootNode).getDocumentElement(); - } else if (rootNode instanceof Element) { - rootElement = (Element) rootNode; - } else { - throw ws.createIllegalArgumentFault("Unexpected DOM node type: " + rootNode); - } - - Object requestObject; - try { - requestObject = prismContext.parserFor(rootElement).parseRealValue(); - } catch (SchemaException e) { - throw ws.createIllegalArgumentFault("Couldn't parse SOAP request body because of schema exception: " + e.getMessage()); - } - - Node response; - Holder operationResultTypeHolder = new Holder<>(); - try { - PrismSerializer serializer = prismContext.domSerializer() - .options(SerializationOptions.createSerializeReferenceNames()); - if (requestObject instanceof GetObjectType) { - GetObjectType g = (GetObjectType) requestObject; - Holder objectTypeHolder = new Holder<>(); - ws.getObject(g.getObjectType(), g.getOid(), g.getOptions(), objectTypeHolder, operationResultTypeHolder); - GetObjectResponseType gr = new GetObjectResponseType(); - gr.setObject(objectTypeHolder.value); - gr.setResult(operationResultTypeHolder.value); - response = serializer.serializeAnyData(gr, ModelPort.GET_OBJECT_RESPONSE); - } else if (requestObject instanceof SearchObjectsType) { - SearchObjectsType s = (SearchObjectsType) requestObject; - Holder objectListTypeHolder = new Holder<>(); - ws.searchObjects(s.getObjectType(), s.getQuery(), s.getOptions(), objectListTypeHolder, operationResultTypeHolder); - SearchObjectsResponseType sr = new SearchObjectsResponseType(); - sr.setObjectList(objectListTypeHolder.value); - sr.setResult(operationResultTypeHolder.value); - response = serializer.serializeAnyData(sr, ModelPort.SEARCH_OBJECTS_RESPONSE); - } else if (requestObject instanceof ExecuteChangesType) { - ExecuteChangesType e = (ExecuteChangesType) requestObject; - ObjectDeltaOperationListType objectDeltaOperationListType = ws.executeChanges(e.getDeltaList(), e.getOptions()); - ExecuteChangesResponseType er = new ExecuteChangesResponseType(); - er.setDeltaOperationList(objectDeltaOperationListType); - response = serializer.serializeAnyData(er, ModelPort.EXECUTE_CHANGES_RESPONSE); - } else if (requestObject instanceof FindShadowOwnerType) { - FindShadowOwnerType f = (FindShadowOwnerType) requestObject; - Holder userTypeHolder = new Holder<>(); - ws.findShadowOwner(f.getShadowOid(), userTypeHolder, operationResultTypeHolder); - FindShadowOwnerResponseType fsr = new FindShadowOwnerResponseType(); - fsr.setUser(userTypeHolder.value); - fsr.setResult(operationResultTypeHolder.value); - response = serializer.serializeAnyData(fsr, ModelPort.FIND_SHADOW_OWNER_RESPONSE); - } else if (requestObject instanceof TestResourceType) { - TestResourceType tr = (TestResourceType) requestObject; - OperationResultType operationResultType = ws.testResource(tr.getResourceOid()); - TestResourceResponseType trr = new TestResourceResponseType(); - trr.setResult(operationResultType); - response = serializer.serializeAnyData(trr, ModelPort.TEST_RESOURCE_RESPONSE); - } else if (requestObject instanceof ExecuteScriptsType) { - ExecuteScriptsType es = (ExecuteScriptsType) requestObject; - ExecuteScriptsResponseType esr = ws.executeScripts(es); - response = serializer.serializeAnyData(esr, ModelPort.EXECUTE_SCRIPTS_RESPONSE); - } else if (requestObject instanceof ImportFromResourceType) { - ImportFromResourceType ifr = (ImportFromResourceType) requestObject; - TaskType taskType = ws.importFromResource(ifr.getResourceOid(), ifr.getObjectClass()); - ImportFromResourceResponseType ifrr = new ImportFromResourceResponseType(); - ifrr.setTask(taskType); - response = serializer.serializeAnyData(ifrr, ModelPort.IMPORT_FROM_RESOURCE_RESPONSE); - } else if (requestObject instanceof NotifyChangeType) { - NotifyChangeType nc = (NotifyChangeType) requestObject; - TaskType taskType = ws.notifyChange(nc.getChangeDescription()); - NotifyChangeResponseType ncr = new NotifyChangeResponseType(); - ncr.setTask(taskType); - response = serializer.serializeAnyData(ncr, ModelPort.NOTIFY_CHANGE_RESPONSE); - } else { - throw ws.createIllegalArgumentFault("Unsupported request type: " + requestObject); - } - } catch (SchemaException e) { - throwFault(e, operationResultTypeHolder.value); - // not reached - return null; - } - - // brutal hack for MID-2001 (serializing and parsing eliminates the problem!) - //String serialized = DOMUtil.printDom(response).toString(); - //LOGGER.trace("WEB SERVICE RESPONSE:\n{}", serialized); - //response = DOMUtil.parseDocument(serialized); - - return new DOMSource(response); - } - - private void serializeFaultMessage(Detail detail, FaultMessage faultMessage) { - prismContext.hacks() - .serializeFaultMessage(detail, faultMessage.getFaultInfo(), SchemaConstants.FAULT_MESSAGE_ELEMENT_NAME, LOGGER); - } - - private void throwFault(Exception ex, OperationResultType resultType) throws FaultMessage { - if (resultType != null) { - ws.throwFault(ex, OperationResult.createOperationResult(resultType)); - } else { - ws.throwFault(ex, null); - } - } -} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/MidpointFunctionsImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/MidpointFunctionsImpl.java index ef641438565..cf48794f807 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/MidpointFunctionsImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/MidpointFunctionsImpl.java @@ -6,6 +6,38 @@ */ package com.evolveum.midpoint.model.impl.expr; +import static java.util.Collections.emptySet; +import static java.util.Collections.singleton; +import static org.apache.commons.collections4.CollectionUtils.emptyIfNull; + +import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_CREDENTIALS_PASSWORD; +import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_CREDENTIALS_PASSWORD_VALUE; +import static com.evolveum.midpoint.schema.util.ObjectTypeUtil.createObjectRef; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.TaskExecutionStatusType.RUNNABLE; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.stream.Collectors; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Characters; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.Validate; +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.common.LocalizationService; import com.evolveum.midpoint.common.refinery.RefinedAttributeDefinition; import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; @@ -25,10 +57,9 @@ import com.evolveum.midpoint.model.impl.lens.LensContext; import com.evolveum.midpoint.model.impl.lens.LensFocusContext; import com.evolveum.midpoint.model.impl.lens.LensProjectionContext; -import com.evolveum.midpoint.model.api.context.SynchronizationIntent; import com.evolveum.midpoint.model.impl.messaging.MessageWrapper; -import com.evolveum.midpoint.model.impl.sync.SynchronizationExpressionsEvaluator; import com.evolveum.midpoint.model.impl.sync.SynchronizationContext; +import com.evolveum.midpoint.model.impl.sync.SynchronizationExpressionsEvaluator; import com.evolveum.midpoint.model.impl.sync.SynchronizationServiceUtils; import com.evolveum.midpoint.model.impl.trigger.RecomputeTriggerHandler; import com.evolveum.midpoint.prism.*; @@ -72,42 +103,8 @@ import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.Validate; -import org.jetbrains.annotations.NotNull; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Component; - -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.Context; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamConstants; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.Characters; -import javax.xml.stream.events.EndElement; -import javax.xml.stream.events.StartElement; -import javax.xml.stream.events.XMLEvent; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.stream.Collectors; - -import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_CREDENTIALS_PASSWORD; -import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_CREDENTIALS_PASSWORD_VALUE; -import static com.evolveum.midpoint.schema.util.ObjectTypeUtil.createObjectRef; -import static com.evolveum.midpoint.xml.ns._public.common.common_3.TaskExecutionStatusType.RUNNABLE; -import static java.util.Collections.emptySet; -import static java.util.Collections.singleton; -import static org.apache.commons.collections4.CollectionUtils.emptyIfNull; - /** * @author semancik - * */ @Component public class MidpointFunctionsImpl implements MidpointFunctions { @@ -134,7 +131,6 @@ public class MidpointFunctionsImpl implements MidpointFunctions { @Autowired private TriggerCreatorGlobalState triggerCreatorGlobalState; @Autowired private TaskManager taskManager; @Autowired private SchemaHelper schemaHelper; - @Context HttpServletRequest httpServletRequest; @Autowired @Qualifier("cacheRepositoryService") @@ -762,7 +758,7 @@ public ModelProjectionContext getProjectionContext() { } @Override - public Mapping getMapping() { + public Mapping getMapping() { return ModelExpressionThreadLocalHolder.getMapping(); } @@ -863,7 +859,7 @@ private T resolveReferenceInternal(ObjectReferenceType re if (reference == null) { return null; } - QName type = reference.getType(); // TODO what about implicitly specified types, like in resourceRef? + QName type = reference.getType(); // TODO what about implicitly specified types, like in resourceRef? PrismObjectDefinition objectDefinition = prismContext.getSchemaRegistry() .findObjectDefinitionByType(reference.getType()); if (objectDefinition == null) { @@ -1473,7 +1469,7 @@ public String createRegistrationConfirmationLink(UserType userType) { if (securityPolicy != null && securityPolicy.getAuthentication() != null && securityPolicy.getAuthentication().getSequence() != null && !securityPolicy.getAuthentication().getSequence().isEmpty()) { if (securityPolicy.getRegistration() != null && securityPolicy.getRegistration().getSelfRegistration() != null - && securityPolicy.getRegistration().getSelfRegistration().getAdditionalAuthenticationName() != null) { + && securityPolicy.getRegistration().getSelfRegistration().getAdditionalAuthenticationName() != null) { String resetPasswordSequenceName = securityPolicy.getRegistration().getSelfRegistration().getAdditionalAuthenticationName(); String prefix = createPrefixLinkByAuthSequence(SchemaConstants.CHANNEL_GUI_SELF_REGISTRATION_URI, resetPasswordSequenceName, securityPolicy.getAuthentication().getSequence()); if (prefix != null) { @@ -1517,24 +1513,24 @@ private String createTokenConfirmationLink(String prefix, UserType userType) { return createBaseConfirmationLink(prefix, userType) + "&" + SchemaConstants.TOKEN + "=" + getNonce(userType); } - private String createPrefixLinkByAuthSequence(String channel, String nameOfSequence, Collection sequences){ - AuthenticationSequenceType sequenceByName = null; - AuthenticationSequenceType defaultSequence = null; - for (AuthenticationSequenceType sequenceType : sequences) { - if (sequenceType.getName().equals(nameOfSequence)) { - sequenceByName = sequenceType; - break; - } else if (sequenceType.getChannel().getChannelId().equals(channel) - && Boolean.TRUE.equals(sequenceType.getChannel().isDefault())) { - defaultSequence = sequenceType; - } - } - AuthenticationSequenceType usedSequence = sequenceByName != null ? sequenceByName : defaultSequence; - if (usedSequence != null) { - String sequecnceSuffix = usedSequence.getChannel().getUrlSuffix(); - String prefix = (sequecnceSuffix.startsWith("/")) ? sequecnceSuffix : ("/" + sequecnceSuffix); - return SchemaConstants.AUTH_MODULE_PREFIX + prefix; - } + private String createPrefixLinkByAuthSequence(String channel, String nameOfSequence, Collection sequences) { + AuthenticationSequenceType sequenceByName = null; + AuthenticationSequenceType defaultSequence = null; + for (AuthenticationSequenceType sequenceType : sequences) { + if (sequenceType.getName().equals(nameOfSequence)) { + sequenceByName = sequenceType; + break; + } else if (sequenceType.getChannel().getChannelId().equals(channel) + && Boolean.TRUE.equals(sequenceType.getChannel().isDefault())) { + defaultSequence = sequenceType; + } + } + AuthenticationSequenceType usedSequence = sequenceByName != null ? sequenceByName : defaultSequence; + if (usedSequence != null) { + String sequecnceSuffix = usedSequence.getChannel().getUrlSuffix(); + String prefix = (sequecnceSuffix.startsWith("/")) ? sequecnceSuffix : ("/" + sequecnceSuffix); + return SchemaConstants.AUTH_MODULE_PREFIX + prefix; + } return null; } @@ -1622,7 +1618,7 @@ public ShadowType resolveEntitlement(ShadowAssociationType shadowAssociationType LOGGER.trace("No shadowRef in association {}", shadowAssociationType); return null; } - if (shadowRef.asReferenceValue().getObject() != null){ + if (shadowRef.asReferenceValue().getObject() != null) { return (ShadowType) shadowAssociationType.getShadowRef().asReferenceValue().getObject().asObjectable(); } @@ -1654,6 +1650,7 @@ public ExtensionType collectExtensions(AssignmentPathType path, int startAt) ConfigurationException, ExpressionEvaluationException { return AssignmentPath.collectExtensions(path, startAt, modelService, getCurrentTask(), getCurrentResult()); } + @Override public TaskType executeChangesAsynchronously(Collection> deltas, ModelExecuteOptions options, String templateTaskOid) throws SecurityViolationException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException, ObjectAlreadyExistsException, PolicyViolationException { @@ -1676,7 +1673,7 @@ public TaskType executeChangesAsynchronously(Collection> deltas, newTask.setName(PolyStringType.fromOrig("Execute changes")); newTask.setRecurrence(TaskRecurrenceType.SINGLE); } - newTask.setName(PolyStringType.fromOrig(newTask.getName().getOrig() + " " + (int) (Math.random()*10000))); + newTask.setName(PolyStringType.fromOrig(newTask.getName().getOrig() + " " + (int) (Math.random() * 10000))); newTask.setOid(null); newTask.setTaskIdentifier(null); newTask.setOwnerRef(createObjectRef(principal.getFocus(), prismContext)); @@ -1744,9 +1741,9 @@ public Object executeAdHocProvisioningScript(ResourceType resource, String langu @Override public Object executeAdHocProvisioningScript(String resourceOid, String language, String code) - throws SchemaException, ObjectNotFoundException, - ExpressionEvaluationException, CommunicationException, ConfigurationException, - SecurityViolationException, ObjectAlreadyExistsException { + throws SchemaException, ObjectNotFoundException, + ExpressionEvaluationException, CommunicationException, ConfigurationException, + SecurityViolationException, ObjectAlreadyExistsException { OperationProvisioningScriptType script = new OperationProvisioningScriptType(); script.setCode(code); script.setLanguage(language); @@ -1905,7 +1902,7 @@ public boolean hasArchetype(O object, String archetypeOid } } - List archetypeRefs = ((AssignmentHolderType)object).getArchetypeRef(); + List archetypeRefs = ((AssignmentHolderType) object).getArchetypeRef(); if (archetypeOid == null) { return archetypeRefs.isEmpty(); } @@ -2031,7 +2028,7 @@ public List findAssignees(Class type) thr ExpressionEvaluationException { ObjectQuery query = prismContext.queryFor(type) .item(AssignmentHolderType.F_ROLE_MEMBERSHIP_REF) - .ref(getFocusObjectReference().asReferenceValue().clone()) + .ref(getFocusObjectReference().asReferenceValue().clone()) .build(); return searchObjects(type, query, null); } @@ -2064,4 +2061,18 @@ private T getFocusObjectAny() { } return object.asObjectable(); } + + @Override + public void createRecomputeTrigger(Class type, String oid) throws SchemaException, + ObjectAlreadyExistsException, ObjectNotFoundException { + OperationResult result = getCurrentResult(MidpointFunctions.class.getName() + ".createRecomputeTrigger"); + + TriggerType trigger = new TriggerType(prismContext) + .handlerUri(RecomputeTriggerHandler.HANDLER_URI) + .timestamp(XmlTypeConverter.createXMLGregorianCalendar()); + List> itemDeltas = prismContext.deltaFor(type) + .item(ObjectType.F_TRIGGER).add(trigger) + .asItemDeltas(); + repositoryService.modifyObject(type, oid, itemDeltas, result); + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java index 24b25a41116..223391c0c80 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/AssignmentEvaluator.java @@ -722,7 +722,7 @@ private List> resolveTargets(AssignmentPat if (oid == null) { LOGGER.trace("Resolving dynamic target ref"); - if (targetRef.getFilter() == null){ + if (targetRef.getFilter() == null) { throw new SchemaException("The OID and filter are both null in assignment targetRef in "+segment.source); } return resolveTargetsFromFilter(targetClass, targetRef.getFilter(), segment, ctx, result); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java index e2543a7c8fc..41cad83f7d9 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java @@ -956,12 +956,12 @@ private PrismObject executeDelta objectContext.addToExecutedDeltas(objectDeltaOp); if (result.isTracingNormal(ModelExecuteDeltaTraceType.class)) { TraceType trace = new ModelExecuteDeltaTraceType(prismContext) - .delta(objectDeltaOp.clone().toLensObjectDeltaOperationType()); // todo kill operation result? + .delta(objectDeltaOp.clone().toLensObjectDeltaOperationType()); // todo kill operation result? result.addTrace(trace); } } else { if (result.isTracingNormal(ModelExecuteDeltaTraceType.class)) { - LensObjectDeltaOperation objectDeltaOp = new LensObjectDeltaOperation<>(objectDelta); // todo + LensObjectDeltaOperation objectDeltaOp = new LensObjectDeltaOperation<>(objectDelta); // todo TraceType trace = new ModelExecuteDeltaTraceType(prismContext) .delta(objectDeltaOp.toLensObjectDeltaOperationType()); result.addTrace(trace); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java index 2a33379b47b..09aeac6c462 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensElementContext.java @@ -1,850 +1,850 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.model.impl.lens; - -import java.util.*; -import java.util.function.Consumer; - -import com.evolveum.midpoint.model.api.context.SynchronizationIntent; -import com.evolveum.midpoint.prism.ConsistencyCheckScope; -import com.evolveum.midpoint.prism.Objectable; -import com.evolveum.midpoint.prism.delta.*; -import com.evolveum.midpoint.prism.delta.builder.S_ItemEntry; -import com.evolveum.midpoint.prism.equivalence.EquivalenceStrategy; -import com.evolveum.midpoint.prism.util.ObjectDeltaObject; -import com.evolveum.midpoint.schema.DeltaConvertor; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.util.ObjectTypeUtil; -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.ObjectNotFoundException; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import com.evolveum.prism.xml.ns._public.types_3.ChangeTypeType; -import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.Validate; - -import com.evolveum.midpoint.common.crypto.CryptoUtil; -import com.evolveum.midpoint.model.api.context.EvaluatedPolicyRule; -import com.evolveum.midpoint.model.api.context.EvaluatedPolicyRuleTrigger; -import com.evolveum.midpoint.model.api.context.ModelElementContext; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectDefinition; -import com.evolveum.midpoint.schema.util.ShadowUtil; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import org.jetbrains.annotations.NotNull; - -/** - * @author semancik - * - */ -public abstract class LensElementContext implements ModelElementContext, Cloneable { - - private static final long serialVersionUID = 1649567559396392861L; - - private static final Trace LOGGER = TraceManager.getTrace(LensElementContext.class); - - private PrismObject objectOld; - private transient PrismObject objectCurrent; - private PrismObject objectNew; - private ObjectDelta primaryDelta; - @NotNull private final List> executedDeltas = new ArrayList<>(); - @NotNull private final Class objectTypeClass; - private String oid = null; - private int iteration; - private String iterationToken; - - transient private SecurityPolicyType securityPolicy; - - /** - * These are policy state modifications that should be applied. - * Currently we apply them in ChangeExecutor.executeChanges only. - * - * In the future we plan to be able to apply some state modifications even - * if the clockwork is exited in non-standard way (e.g. in primary state or with an exception). - * But we must be sure what policy state to store, because some constraints might be triggered - * because of expectation of future state (like conflicting assignment is added etc.) - * --- - * Although placed in LensElementContext, support for this data is currently implemented only for focus, not for projections. - */ - @NotNull private final List> pendingObjectPolicyStateModifications = new ArrayList<>(); - - /** - * Policy state modifications for assignments. - * - * Although we put here also deltas for assignments that are to be deleted, we do not execute these - * (because we implement execution only for the standard exit-path from the clockwork). - */ - @NotNull private final Map>> pendingAssignmentPolicyStateModifications = new HashMap<>(); - - private SynchronizationIntent synchronizationIntent; - - private transient boolean isFresh = false; - - private LensContext lensContext; - - private transient PrismObjectDefinition objectDefinition = null; - - private final Collection policyRules = new ArrayList<>(); - private final Collection policySituations = new ArrayList<>(); - - public LensElementContext(@NotNull Class objectTypeClass, LensContext lensContext) { - super(); - Validate.notNull(objectTypeClass, "Object class is null"); - Validate.notNull(lensContext, "Lens context is null"); - this.lensContext = lensContext; - this.objectTypeClass = objectTypeClass; - } - - public int getIteration() { - return iteration; - } - - public void setIteration(int iteration) { - this.iteration = iteration; - } - - public String getIterationToken() { - return iterationToken; - } - - public void setIterationToken(String iterationToken) { - this.iterationToken = iterationToken; - } - - public SynchronizationIntent getSynchronizationIntent() { - return synchronizationIntent; - } - - public void setSynchronizationIntent(SynchronizationIntent synchronizationIntent) { - this.synchronizationIntent = synchronizationIntent; - } - - public LensContext getLensContext() { - return lensContext; - } - - protected PrismContext getNotNullPrismContext() { - return getLensContext().getNotNullPrismContext(); - } - - @Override - public Class getObjectTypeClass() { - return objectTypeClass; - } - - public boolean represents(Class type) { - return type.isAssignableFrom(objectTypeClass); - } - - public PrismContext getPrismContext() { - return lensContext.getPrismContext(); - } - - @Override - public PrismObject getObjectOld() { - return objectOld; - } - - public void setObjectOld(PrismObject objectOld) { - this.objectOld = objectOld; - } - - @Override - public PrismObject getObjectCurrent() { - return objectCurrent; - } - - public void setObjectCurrent(PrismObject objectCurrent) { - this.objectCurrent = objectCurrent; - } - - public PrismObject getObjectAny() { - if (objectNew != null) { - return objectNew; - } - if (objectCurrent != null) { - return objectCurrent; - } - return objectOld; - } - - /** - * Sets current and possibly also old object. This method is used with - * freshly loaded object. The object is set as current object. - * If the old object was not initialized yet (and if it should be initialized) - * then the object is also set as old object. - */ - public void setLoadedObject(PrismObject object) { - setObjectCurrent(object); - if (objectOld == null && !isAdd()) { - setObjectOld(object.clone()); - } - } - - @Override - public PrismObject getObjectNew() { - return objectNew; - } - - public void setObjectNew(PrismObject objectNew) { - this.objectNew = objectNew; - } - - @Override - public ObjectDelta getPrimaryDelta() { - return primaryDelta; - } - - public boolean hasPrimaryDelta() { - return primaryDelta != null && !primaryDelta.isEmpty(); - } - - /** - * As getPrimaryDelta() but caters for the possibility that an object already exists. - * So, if the primary delta is ADD and object already exists, it should be changed somehow, - * e.g. to MODIFY delta or to null. - * - * Actually, the question is what to do with the attribute values if changed to MODIFY. - * (a) Should they become REPLACE item deltas? (b) ADD ones? - * (c) Or should we compute a difference from objectCurrent to objectToAdd, hoping that - * secondary deltas will re-add everything that might be unknowingly removed by this step? - * (d) Or should we simply ignore ADD delta altogether, hoping that it was executed - * so it need not be repeated? - * - * And, should not we report AlreadyExistingException instead? - * - * It seems that (c) i.e. reverting back to objectToAdd is not a good idea at all. For example, this - * may erase linkRefs for good. - * - * For the time being let us proceed with (d), i.e. ignoring such a delta. - * - * TODO is this OK???? [med] - * - * @return - */ - public ObjectDelta getFixedPrimaryDelta() { - if (primaryDelta == null || !primaryDelta.isAdd() || objectCurrent == null) { - return primaryDelta; // nothing to do - } - // Object does exist. Let's ignore the delta - see description above. - return null; - } - - public void setPrimaryDelta(ObjectDelta primaryDelta) { - this.primaryDelta = primaryDelta; - } - - public void addPrimaryDelta(ObjectDelta delta) throws SchemaException { - if (primaryDelta == null) { - primaryDelta = delta; - } else { - primaryDelta.merge(delta); - } - } - - public void swallowToPrimaryDelta(ItemDelta itemDelta) throws SchemaException { - modifyOrCreatePrimaryDelta( - delta -> delta.swallow(itemDelta), - () -> { - ObjectDelta newPrimaryDelta = getPrismContext().deltaFactory().object().create(getObjectTypeClass(), ChangeType.MODIFY); - newPrimaryDelta.setOid(oid); - newPrimaryDelta.addModification(itemDelta); - return newPrimaryDelta; - }); - } - - @FunctionalInterface - private interface DeltaModifier { - void modify(ObjectDelta delta) throws SchemaException; - } - - @FunctionalInterface - private interface DeltaCreator { - ObjectDelta create() throws SchemaException; - } - - private void modifyOrCreatePrimaryDelta(DeltaModifier modifier, DeltaCreator creator) throws SchemaException { - if (primaryDelta == null) { - primaryDelta = creator.create(); - } else if (!primaryDelta.isImmutable()) { - modifier.modify(primaryDelta); - } else { - primaryDelta = primaryDelta.clone(); - modifier.modify(primaryDelta); - primaryDelta.freeze(); - } - } - - public abstract void swallowToSecondaryDelta(ItemDelta itemDelta) throws SchemaException; - - // TODO deduplicate with swallowToSecondaryDelta in LensFocusContext - public ObjectDelta swallowToDelta(ObjectDelta originalDelta, ItemDelta propDelta) throws SchemaException { - if (originalDelta == null) { - originalDelta = getPrismContext().deltaFactory().object().create(getObjectTypeClass(), ChangeType.MODIFY); - originalDelta.setOid(getOid()); - } else if (originalDelta.containsModification(propDelta, EquivalenceStrategy.LITERAL_IGNORE_METADATA)) { // todo why literal? - return originalDelta; - } - originalDelta.swallow(propDelta); - return originalDelta; - } - - /** - * Returns collection of all deltas that this element context contains. - * This is a nice method to use if we want to inspect all deltas (e.g. look for a changed item) - * but we want to avoid the overhead of merging all the deltas together. - */ - public abstract Collection> getAllDeltas(); - - @NotNull - public List> getPendingObjectPolicyStateModifications() { - return pendingObjectPolicyStateModifications; - } - - public void clearPendingObjectPolicyStateModifications() { - pendingObjectPolicyStateModifications.clear(); - } - - public void addToPendingObjectPolicyStateModifications(ItemDelta modification) { - pendingObjectPolicyStateModifications.add(modification); - } - - @NotNull - public Map>> getPendingAssignmentPolicyStateModifications() { - return pendingAssignmentPolicyStateModifications; - } - - public void clearPendingAssignmentPolicyStateModifications() { - pendingAssignmentPolicyStateModifications.clear(); - } - - public void addToPendingAssignmentPolicyStateModifications(@NotNull AssignmentType assignment, @NotNull PlusMinusZero mode, @NotNull ItemDelta modification) { - AssignmentSpec spec = new AssignmentSpec(assignment, mode); - pendingAssignmentPolicyStateModifications.computeIfAbsent(spec, k -> new ArrayList<>()).add(modification); - } - - public boolean isModify() { - // TODO I'm not sure why isModify checks both primary and secondary deltas for focus context, while - // isAdd and isDelete care only for the primary delta. - return ObjectDelta.isModify(getPrimaryDelta()) || ObjectDelta.isModify(getSecondaryDelta()); - } - - @NotNull - public SimpleOperationName getOperation() { - if (isAdd()) { - return SimpleOperationName.ADD; - } else if (isDelete()) { - return SimpleOperationName.DELETE; - } else { - return SimpleOperationName.MODIFY; - } - } - - @NotNull - @Override - public List> getExecutedDeltas() { - return executedDeltas; - } - - List> getExecutedDeltas(Boolean audited) { - if (audited == null) { - return executedDeltas; - } - List> deltas = new ArrayList<>(); - for (LensObjectDeltaOperation delta: executedDeltas) { - if (delta.isAudited() == audited) { - deltas.add(delta); - } - } - return deltas; - } - - public void markExecutedDeltasAudited() { - for(LensObjectDeltaOperation executedDelta: executedDeltas) { - executedDelta.setAudited(true); - } - } - - public void addToExecutedDeltas(LensObjectDeltaOperation executedDelta) { - executedDeltas.add(executedDelta.clone()); // must be cloned because e.g. for ADD deltas the object gets modified afterwards - } - - /** - * Returns user delta, both primary and secondary (merged together). - * The returned object is (kind of) immutable. Changing it may do strange things (but most likely the changes will be lost). - */ - public ObjectDelta getDelta() throws SchemaException { - return ObjectDeltaCollectionsUtil.union(primaryDelta, getSecondaryDelta()); - } - - public ObjectDelta getFixedDelta() throws SchemaException { - return ObjectDeltaCollectionsUtil.union(getFixedPrimaryDelta(), getSecondaryDelta()); - } - - public boolean wasAddExecuted() { - - for (LensObjectDeltaOperation executedDeltaOperation : getExecutedDeltas()){ - ObjectDelta executedDelta = executedDeltaOperation.getObjectDelta(); - if (!executedDelta.isAdd()){ - continue; - } else if (executedDelta.getObjectToAdd() != null && executedDelta.getObjectTypeClass().equals(getObjectTypeClass())){ - return true; - } - } - - return false; - } - - abstract public ObjectDeltaObject getObjectDeltaObject() throws SchemaException; - - @Override - public String getOid() { - if (oid == null) { - oid = determineOid(); - } - return oid; - } - - public String determineOid() { - if (getObjectOld() != null && getObjectOld().getOid() != null) { - return getObjectOld().getOid(); - } - if (getObjectCurrent() != null && getObjectCurrent().getOid() != null) { - return getObjectCurrent().getOid(); - } - if (getObjectNew() != null && getObjectNew().getOid() != null) { - return getObjectNew().getOid(); - } - if (getPrimaryDelta() != null && getPrimaryDelta().getOid() != null) { - return getPrimaryDelta().getOid(); - } - if (getSecondaryDelta() != null && getSecondaryDelta().getOid() != null) { - return getSecondaryDelta().getOid(); - } - return null; - } - - /** - * Sets oid to the field but also to the deltas (if applicable). - */ - public void setOid(String oid) { - this.oid = oid; - if (primaryDelta != null && !primaryDelta.isImmutable()) { - primaryDelta.setOid(oid); - } - // TODO What if primary delta is immutable ADD delta and objectNew was taken from it? - // It would be immutable as well in that case. We will see. - if (objectNew != null) { - objectNew.setOid(oid); - } - } - - public PrismObjectDefinition getObjectDefinition() { - if (objectDefinition == null) { - if (objectOld != null) { - objectDefinition = objectOld.getDefinition(); - } else if (objectCurrent != null) { - objectDefinition = objectCurrent.getDefinition(); - } else if (objectNew != null) { - objectDefinition = objectNew.getDefinition(); - } else { - objectDefinition = getNotNullPrismContext().getSchemaRegistry().findObjectDefinitionByCompileTimeClass(getObjectTypeClass()); - } - } - return objectDefinition; - } - - public boolean isFresh() { - return isFresh; - } - - public void setFresh(boolean isFresh) { - this.isFresh = isFresh; - } - - @NotNull - public Collection getPolicyRules() { - return policyRules; - } - - public void addPolicyRule(EvaluatedPolicyRule policyRule) { - this.policyRules.add(policyRule); - } - - public void clearPolicyRules() { - policyRules.clear(); - } - - public void triggerRule(@NotNull EvaluatedPolicyRule rule, Collection> triggers) { - LensUtil.triggerRule(rule, triggers, policySituations); - } - - @NotNull - public Collection getPolicySituations() { - return policySituations; - } - - /** - * Returns security policy applicable to the object. This means security policy - * applicable directory to focus or projection. It will NOT return global - * security policy. - */ - public SecurityPolicyType getSecurityPolicy() { - return securityPolicy; - } - - public void setSecurityPolicy(SecurityPolicyType securityPolicy) { - this.securityPolicy = securityPolicy; - } - - public CredentialsPolicyType getCredentialsPolicy() { - return securityPolicy != null ? securityPolicy.getCredentials() : null; - } - - public void recompute() throws SchemaException, ConfigurationException { - PrismObject base = getObjectCurrentOrOld(); - ObjectDelta delta = getDelta(); - if (delta == null) { - // No change - objectNew = base; - return; - } - objectNew = delta.computeChangedObject(base); - } - - public void checkConsistence() { - checkConsistence(null); - } - - public void checkConsistence(String contextDesc) { - if (getObjectOld() != null) { - checkConsistence(getObjectOld(), "old "+getElementDesc() , contextDesc); - } - if (getObjectCurrent() != null) { - checkConsistence(getObjectCurrent(), "current "+getElementDesc() , contextDesc); - } - if (primaryDelta != null) { - checkConsistence(primaryDelta, false, getElementDesc()+" primary delta in "+this + (contextDesc == null ? "" : " in " +contextDesc)); - } - if (getObjectNew() != null) { - checkConsistence(getObjectNew(), "new "+getElementDesc(), contextDesc); - } - } - - protected void checkConsistence(ObjectDelta delta, boolean requireOid, String contextDesc) { - try { - delta.checkConsistence(requireOid, true, true, ConsistencyCheckScope.THOROUGH); - } catch (IllegalArgumentException e) { - throw new IllegalArgumentException(e.getMessage()+"; in "+contextDesc, e); - } catch (IllegalStateException e) { - throw new IllegalStateException(e.getMessage()+"; in "+contextDesc, e); - } - if (delta.isAdd()) { - checkConsistence(delta.getObjectToAdd(), "add object", contextDesc); - } - } - - protected boolean isRequireSecondaryDeltaOid() { - return primaryDelta == null; - } - - protected void checkConsistence(PrismObject object, String elementDesc, String contextDesc) { - String desc = elementDesc+" in "+this + (contextDesc == null ? "" : " in " +contextDesc); - try { - object.checkConsistence(true, ConsistencyCheckScope.THOROUGH); - } catch (IllegalArgumentException e) { - throw new IllegalArgumentException(e.getMessage()+"; in "+desc, e); - } catch (IllegalStateException e) { - throw new IllegalStateException(e.getMessage()+"; in "+desc, e); - } - if (object.getDefinition() == null) { - throw new IllegalStateException("No "+getElementDesc()+" definition "+desc); - } - O objectType = object.asObjectable(); - if (objectType instanceof ShadowType) { - ShadowUtil.checkConsistence((PrismObject) object, desc); - } - } - - /** - * Cleans up the contexts by removing some of the working state. - */ - public abstract void cleanup(); - - public void normalize() { - if (objectNew != null) { - objectNew.normalize(); - } - if (objectOld != null) { - objectOld.normalize(); - } - if (objectCurrent != null) { - objectCurrent.normalize(); - } - if (primaryDelta != null && !primaryDelta.isImmutable()) { - primaryDelta.normalize(); - } - } - - public void adopt(PrismContext prismContext) throws SchemaException { - if (objectNew != null) { - prismContext.adopt(objectNew); - } - if (objectOld != null) { - prismContext.adopt(objectOld); - } - if (objectCurrent != null) { - prismContext.adopt(objectCurrent); - } - if (primaryDelta != null) { - prismContext.adopt(primaryDelta); - } - // TODO: object definition? - } - - public abstract LensElementContext clone(LensContext lensContext); - - void copyValues(LensElementContext clone, LensContext lensContext) { - //noinspection unchecked - clone.lensContext = lensContext; - // This is de-facto immutable - clone.objectDefinition = this.objectDefinition; - clone.objectNew = cloneObject(this.objectNew); - clone.objectOld = cloneObject(this.objectOld); - clone.objectCurrent = cloneObject(this.objectCurrent); - clone.oid = this.oid; - clone.primaryDelta = cloneDelta(this.primaryDelta); - clone.isFresh = this.isFresh; - clone.iteration = this.iteration; - clone.iterationToken = this.iterationToken; - clone.securityPolicy = this.securityPolicy; - } - - protected ObjectDelta cloneDelta(ObjectDelta thisDelta) { - if (thisDelta == null) { - return null; - } - return thisDelta.clone(); - } - - private PrismObject cloneObject(PrismObject thisObject) { - if (thisObject == null) { - return null; - } - return thisObject.clone(); - } - - void storeIntoLensElementContextType(LensElementContextType lensElementContextType, LensContext.ExportType exportType) throws SchemaException { - if (objectOld != null && exportType != LensContext.ExportType.MINIMAL) { - if (exportType == LensContext.ExportType.REDUCED) { - lensElementContextType.setObjectOldRef(ObjectTypeUtil.createObjectRef(objectOld, getPrismContext())); - } else { - lensElementContextType.setObjectOld(objectOld.asObjectable().clone()); - } - } - if (objectCurrent != null && exportType == LensContext.ExportType.TRACE) { - lensElementContextType.setObjectCurrent(objectCurrent.asObjectable().clone()); - } - if (objectNew != null && exportType != LensContext.ExportType.MINIMAL) { - if (exportType == LensContext.ExportType.REDUCED) { - lensElementContextType.setObjectNewRef(ObjectTypeUtil.createObjectRef(objectNew, getPrismContext())); - } else { - lensElementContextType.setObjectNew(objectNew.asObjectable().clone()); - } - } - if (exportType != LensContext.ExportType.MINIMAL) { - lensElementContextType.setPrimaryDelta(primaryDelta != null ? DeltaConvertor.toObjectDeltaType(primaryDelta) : null); - for (LensObjectDeltaOperation executedDelta : executedDeltas) { - lensElementContextType.getExecutedDeltas() - .add(LensContext.simplifyExecutedDelta(executedDelta).toLensObjectDeltaOperationType()); - } - lensElementContextType.setObjectTypeClass(objectTypeClass != null ? objectTypeClass.getName() : null); - lensElementContextType.setOid(oid); - lensElementContextType.setIteration(iteration); - lensElementContextType.setIterationToken(iterationToken); - lensElementContextType.setSynchronizationIntent( - synchronizationIntent != null ? synchronizationIntent.toSynchronizationIntentType() : null); - } - lensElementContextType.setFresh(isFresh); - } - - public void retrieveFromLensElementContextType(LensElementContextType lensElementContextType, Task task, OperationResult result) throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ExpressionEvaluationException { - - ObjectType objectTypeOld = lensElementContextType.getObjectOld(); - this.objectOld = objectTypeOld != null ? (PrismObject) objectTypeOld.asPrismObject() : null; - fixProvisioningTypeInObject(this.objectOld, task, result); - - ObjectType objectTypeNew = lensElementContextType.getObjectNew(); - this.objectNew = objectTypeNew != null ? (PrismObject) objectTypeNew.asPrismObject() : null; - fixProvisioningTypeInObject(this.objectNew, task, result); - - ObjectType object = objectTypeNew != null ? objectTypeNew : objectTypeOld; - - ObjectDeltaType primaryDeltaType = lensElementContextType.getPrimaryDelta(); - this.primaryDelta = primaryDeltaType != null ? (ObjectDelta) DeltaConvertor.createObjectDelta(primaryDeltaType, lensContext.getPrismContext()) : null; - fixProvisioningTypeInDelta(this.primaryDelta, object, task, result); - - for (LensObjectDeltaOperationType eDeltaOperationType : lensElementContextType.getExecutedDeltas()) { - LensObjectDeltaOperation objectDeltaOperation = LensObjectDeltaOperation.fromLensObjectDeltaOperationType(eDeltaOperationType, lensContext.getPrismContext()); - if (objectDeltaOperation.getObjectDelta() != null) { - fixProvisioningTypeInDelta(objectDeltaOperation.getObjectDelta(), object, task, result); - } - this.executedDeltas.add(objectDeltaOperation); - } - - this.oid = lensElementContextType.getOid(); - - this.iteration = lensElementContextType.getIteration() != null ? lensElementContextType.getIteration() : 0; - this.iterationToken = lensElementContextType.getIterationToken(); - this.synchronizationIntent = SynchronizationIntent.fromSynchronizationIntentType(lensElementContextType.getSynchronizationIntent()); - - // note: objectTypeClass is already converted (used in the constructor) - } - - protected void fixProvisioningTypeInDelta(ObjectDelta delta, Objectable object, Task task, OperationResult result) { - if (delta != null && delta.getObjectTypeClass() != null && (ShadowType.class.isAssignableFrom(delta.getObjectTypeClass()) || ResourceType.class.isAssignableFrom(delta.getObjectTypeClass()))) { - try { - lensContext.getProvisioningService().applyDefinition(delta, object, task, result); - } catch (Exception e) { - LOGGER.warn("Error applying provisioning definitions to delta {}: {}", delta, e.getMessage()); - // In case of error just go on. Maybe we do not have correct definition here. But at least we can - // display the GUI pages and maybe we can also salvage the operation. - result.recordWarning(e); - } - } - } - - private void fixProvisioningTypeInObject(PrismObject object, Task task, OperationResult result) { - if (object != null && object.getCompileTimeClass() != null && (ShadowType.class.isAssignableFrom(object.getCompileTimeClass()) || ResourceType.class.isAssignableFrom(object.getCompileTimeClass()))) { - try { - lensContext.getProvisioningService().applyDefinition(object, task, result); - } catch (Exception e) { - LOGGER.warn("Error applying provisioning definitions to object {}: {}", object, e.getMessage()); - // In case of error just go on. Maybe we do not have correct definition here. But at least we can - // display the GUI pages and maybe we can also salvage the operation. - result.recordWarning(e); - } - } - } - - public void checkEncrypted() { - if (objectNew != null) { - CryptoUtil.checkEncrypted(objectNew); - } - if (objectOld != null) { - CryptoUtil.checkEncrypted(objectOld); - } - if (objectCurrent != null) { - CryptoUtil.checkEncrypted(objectCurrent); - } - if (primaryDelta != null) { - CryptoUtil.checkEncrypted(primaryDelta); - } - } - - public boolean operationMatches(ChangeTypeType operation) { - switch (operation) { - case ADD: - return getOperation() == SimpleOperationName.ADD; - case MODIFY: - return getOperation() == SimpleOperationName.MODIFY; - case DELETE: - return getOperation() == SimpleOperationName.DELETE; - } - throw new IllegalArgumentException("Unknown operation "+operation); - } - - protected abstract String getElementDefaultDesc(); - - protected String getElementDesc() { - PrismObject object = getObjectNew(); - if (object == null) { - object = getObjectOld(); - } - if (object == null) { - object = getObjectCurrent(); - } - if (object == null) { - return getElementDefaultDesc(); - } - return object.toDebugType(); - } - - protected String getDebugDumpTitle() { - return StringUtils.capitalize(getElementDesc()); - } - - protected String getDebugDumpTitle(String suffix) { - return getDebugDumpTitle()+" "+suffix; - } - - public abstract String getHumanReadableName(); - - public String getObjectReadVersion() { - // Do NOT use version from object current. - // Current object may be re-read, but the computation - // might be based on older data (objectOld). -// if (getObjectCurrent() != null) { -// return getObjectCurrent().getVersion(); -// } - if (getObjectOld() != null) { - return getObjectOld().getVersion(); - } - return null; - } - - public PrismObject getObjectCurrentOrOld() { - return objectCurrent != null ? objectCurrent : objectOld; - } - - @Override - public boolean isOfType(Class aClass) { - if (aClass.isAssignableFrom(objectTypeClass)) { - return true; - } - PrismObject object = getObjectAny(); - return object != null && aClass.isAssignableFrom(object.asObjectable().getClass()); - } - - public abstract void deleteSecondaryDeltas(); - - public S_ItemEntry deltaBuilder() throws SchemaException { - return getPrismContext().deltaFor(getObjectTypeClass()); - } - - public void forEachObject(Consumer> consumer) { - if (objectCurrent != null) { - consumer.accept(objectCurrent); - } - if (objectOld != null) { - consumer.accept(objectOld); - } - if (objectNew != null) { - consumer.accept(objectNew); - } - } - - public void forEachDelta(Consumer> consumer) { - if (primaryDelta != null) { - consumer.accept(primaryDelta); - } - } - - public void finishBuild() { - if (primaryDelta != null) { - primaryDelta.normalize(); - primaryDelta.freeze(); - } - } -} +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.model.impl.lens; + +import java.util.*; +import java.util.function.Consumer; + +import com.evolveum.midpoint.model.api.context.SynchronizationIntent; +import com.evolveum.midpoint.prism.ConsistencyCheckScope; +import com.evolveum.midpoint.prism.Objectable; +import com.evolveum.midpoint.prism.delta.*; +import com.evolveum.midpoint.prism.delta.builder.S_ItemEntry; +import com.evolveum.midpoint.prism.equivalence.EquivalenceStrategy; +import com.evolveum.midpoint.prism.util.ObjectDeltaObject; +import com.evolveum.midpoint.schema.DeltaConvertor; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.ObjectTypeUtil; +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.ObjectNotFoundException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import com.evolveum.prism.xml.ns._public.types_3.ChangeTypeType; +import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.Validate; + +import com.evolveum.midpoint.common.crypto.CryptoUtil; +import com.evolveum.midpoint.model.api.context.EvaluatedPolicyRule; +import com.evolveum.midpoint.model.api.context.EvaluatedPolicyRuleTrigger; +import com.evolveum.midpoint.model.api.context.ModelElementContext; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismObjectDefinition; +import com.evolveum.midpoint.schema.util.ShadowUtil; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import org.jetbrains.annotations.NotNull; + +/** + * @author semancik + * + */ +public abstract class LensElementContext implements ModelElementContext, Cloneable { + + private static final long serialVersionUID = 1649567559396392861L; + + private static final Trace LOGGER = TraceManager.getTrace(LensElementContext.class); + + private PrismObject objectOld; + private transient PrismObject objectCurrent; + private PrismObject objectNew; + private ObjectDelta primaryDelta; + @NotNull private final List> executedDeltas = new ArrayList<>(); + @NotNull private final Class objectTypeClass; + private String oid = null; + private int iteration; + private String iterationToken; + + transient private SecurityPolicyType securityPolicy; + + /** + * These are policy state modifications that should be applied. + * Currently we apply them in ChangeExecutor.executeChanges only. + * + * In the future we plan to be able to apply some state modifications even + * if the clockwork is exited in non-standard way (e.g. in primary state or with an exception). + * But we must be sure what policy state to store, because some constraints might be triggered + * because of expectation of future state (like conflicting assignment is added etc.) + * --- + * Although placed in LensElementContext, support for this data is currently implemented only for focus, not for projections. + */ + @NotNull private final List> pendingObjectPolicyStateModifications = new ArrayList<>(); + + /** + * Policy state modifications for assignments. + * + * Although we put here also deltas for assignments that are to be deleted, we do not execute these + * (because we implement execution only for the standard exit-path from the clockwork). + */ + @NotNull private final Map>> pendingAssignmentPolicyStateModifications = new HashMap<>(); + + private SynchronizationIntent synchronizationIntent; + + private transient boolean isFresh = false; + + private LensContext lensContext; + + private transient PrismObjectDefinition objectDefinition = null; + + private final Collection policyRules = new ArrayList<>(); + private final Collection policySituations = new ArrayList<>(); + + public LensElementContext(@NotNull Class objectTypeClass, LensContext lensContext) { + super(); + Validate.notNull(objectTypeClass, "Object class is null"); + Validate.notNull(lensContext, "Lens context is null"); + this.lensContext = lensContext; + this.objectTypeClass = objectTypeClass; + } + + public int getIteration() { + return iteration; + } + + public void setIteration(int iteration) { + this.iteration = iteration; + } + + public String getIterationToken() { + return iterationToken; + } + + public void setIterationToken(String iterationToken) { + this.iterationToken = iterationToken; + } + + public SynchronizationIntent getSynchronizationIntent() { + return synchronizationIntent; + } + + public void setSynchronizationIntent(SynchronizationIntent synchronizationIntent) { + this.synchronizationIntent = synchronizationIntent; + } + + public LensContext getLensContext() { + return lensContext; + } + + protected PrismContext getNotNullPrismContext() { + return getLensContext().getNotNullPrismContext(); + } + + @Override + public Class getObjectTypeClass() { + return objectTypeClass; + } + + public boolean represents(Class type) { + return type.isAssignableFrom(objectTypeClass); + } + + public PrismContext getPrismContext() { + return lensContext.getPrismContext(); + } + + @Override + public PrismObject getObjectOld() { + return objectOld; + } + + public void setObjectOld(PrismObject objectOld) { + this.objectOld = objectOld; + } + + @Override + public PrismObject getObjectCurrent() { + return objectCurrent; + } + + public void setObjectCurrent(PrismObject objectCurrent) { + this.objectCurrent = objectCurrent; + } + + public PrismObject getObjectAny() { + if (objectNew != null) { + return objectNew; + } + if (objectCurrent != null) { + return objectCurrent; + } + return objectOld; + } + + /** + * Sets current and possibly also old object. This method is used with + * freshly loaded object. The object is set as current object. + * If the old object was not initialized yet (and if it should be initialized) + * then the object is also set as old object. + */ + public void setLoadedObject(PrismObject object) { + setObjectCurrent(object); + if (objectOld == null && !isAdd()) { + setObjectOld(object.clone()); + } + } + + @Override + public PrismObject getObjectNew() { + return objectNew; + } + + public void setObjectNew(PrismObject objectNew) { + this.objectNew = objectNew; + } + + @Override + public ObjectDelta getPrimaryDelta() { + return primaryDelta; + } + + public boolean hasPrimaryDelta() { + return primaryDelta != null && !primaryDelta.isEmpty(); + } + + /** + * As getPrimaryDelta() but caters for the possibility that an object already exists. + * So, if the primary delta is ADD and object already exists, it should be changed somehow, + * e.g. to MODIFY delta or to null. + * + * Actually, the question is what to do with the attribute values if changed to MODIFY. + * (a) Should they become REPLACE item deltas? (b) ADD ones? + * (c) Or should we compute a difference from objectCurrent to objectToAdd, hoping that + * secondary deltas will re-add everything that might be unknowingly removed by this step? + * (d) Or should we simply ignore ADD delta altogether, hoping that it was executed + * so it need not be repeated? + * + * And, should not we report AlreadyExistingException instead? + * + * It seems that (c) i.e. reverting back to objectToAdd is not a good idea at all. For example, this + * may erase linkRefs for good. + * + * For the time being let us proceed with (d), i.e. ignoring such a delta. + * + * TODO is this OK???? [med] + * + * @return + */ + public ObjectDelta getFixedPrimaryDelta() { + if (primaryDelta == null || !primaryDelta.isAdd() || objectCurrent == null) { + return primaryDelta; // nothing to do + } + // Object does exist. Let's ignore the delta - see description above. + return null; + } + + public void setPrimaryDelta(ObjectDelta primaryDelta) { + this.primaryDelta = primaryDelta; + } + + public void addPrimaryDelta(ObjectDelta delta) throws SchemaException { + if (primaryDelta == null) { + primaryDelta = delta; + } else { + primaryDelta.merge(delta); + } + } + + public void swallowToPrimaryDelta(ItemDelta itemDelta) throws SchemaException { + modifyOrCreatePrimaryDelta( + delta -> delta.swallow(itemDelta), + () -> { + ObjectDelta newPrimaryDelta = getPrismContext().deltaFactory().object().create(getObjectTypeClass(), ChangeType.MODIFY); + newPrimaryDelta.setOid(oid); + newPrimaryDelta.addModification(itemDelta); + return newPrimaryDelta; + }); + } + + @FunctionalInterface + private interface DeltaModifier { + void modify(ObjectDelta delta) throws SchemaException; + } + + @FunctionalInterface + private interface DeltaCreator { + ObjectDelta create() throws SchemaException; + } + + private void modifyOrCreatePrimaryDelta(DeltaModifier modifier, DeltaCreator creator) throws SchemaException { + if (primaryDelta == null) { + primaryDelta = creator.create(); + } else if (!primaryDelta.isImmutable()) { + modifier.modify(primaryDelta); + } else { + primaryDelta = primaryDelta.clone(); + modifier.modify(primaryDelta); + primaryDelta.freeze(); + } + } + + public abstract void swallowToSecondaryDelta(ItemDelta itemDelta) throws SchemaException; + + // TODO deduplicate with swallowToSecondaryDelta in LensFocusContext + public ObjectDelta swallowToDelta(ObjectDelta originalDelta, ItemDelta propDelta) throws SchemaException { + if (originalDelta == null) { + originalDelta = getPrismContext().deltaFactory().object().create(getObjectTypeClass(), ChangeType.MODIFY); + originalDelta.setOid(getOid()); + } else if (originalDelta.containsModification(propDelta, EquivalenceStrategy.LITERAL_IGNORE_METADATA)) { // todo why literal? + return originalDelta; + } + originalDelta.swallow(propDelta); + return originalDelta; + } + + /** + * Returns collection of all deltas that this element context contains. + * This is a nice method to use if we want to inspect all deltas (e.g. look for a changed item) + * but we want to avoid the overhead of merging all the deltas together. + */ + public abstract Collection> getAllDeltas(); + + @NotNull + public List> getPendingObjectPolicyStateModifications() { + return pendingObjectPolicyStateModifications; + } + + public void clearPendingObjectPolicyStateModifications() { + pendingObjectPolicyStateModifications.clear(); + } + + public void addToPendingObjectPolicyStateModifications(ItemDelta modification) { + pendingObjectPolicyStateModifications.add(modification); + } + + @NotNull + public Map>> getPendingAssignmentPolicyStateModifications() { + return pendingAssignmentPolicyStateModifications; + } + + public void clearPendingAssignmentPolicyStateModifications() { + pendingAssignmentPolicyStateModifications.clear(); + } + + public void addToPendingAssignmentPolicyStateModifications(@NotNull AssignmentType assignment, @NotNull PlusMinusZero mode, @NotNull ItemDelta modification) { + AssignmentSpec spec = new AssignmentSpec(assignment, mode); + pendingAssignmentPolicyStateModifications.computeIfAbsent(spec, k -> new ArrayList<>()).add(modification); + } + + public boolean isModify() { + // TODO I'm not sure why isModify checks both primary and secondary deltas for focus context, while + // isAdd and isDelete care only for the primary delta. + return ObjectDelta.isModify(getPrimaryDelta()) || ObjectDelta.isModify(getSecondaryDelta()); + } + + @NotNull + public SimpleOperationName getOperation() { + if (isAdd()) { + return SimpleOperationName.ADD; + } else if (isDelete()) { + return SimpleOperationName.DELETE; + } else { + return SimpleOperationName.MODIFY; + } + } + + @NotNull + @Override + public List> getExecutedDeltas() { + return executedDeltas; + } + + List> getExecutedDeltas(Boolean audited) { + if (audited == null) { + return executedDeltas; + } + List> deltas = new ArrayList<>(); + for (LensObjectDeltaOperation delta: executedDeltas) { + if (delta.isAudited() == audited) { + deltas.add(delta); + } + } + return deltas; + } + + public void markExecutedDeltasAudited() { + for(LensObjectDeltaOperation executedDelta: executedDeltas) { + executedDelta.setAudited(true); + } + } + + public void addToExecutedDeltas(LensObjectDeltaOperation executedDelta) { + executedDeltas.add(executedDelta.clone()); // must be cloned because e.g. for ADD deltas the object gets modified afterwards + } + + /** + * Returns user delta, both primary and secondary (merged together). + * The returned object is (kind of) immutable. Changing it may do strange things (but most likely the changes will be lost). + */ + public ObjectDelta getDelta() throws SchemaException { + return ObjectDeltaCollectionsUtil.union(primaryDelta, getSecondaryDelta()); + } + + public ObjectDelta getFixedDelta() throws SchemaException { + return ObjectDeltaCollectionsUtil.union(getFixedPrimaryDelta(), getSecondaryDelta()); + } + + public boolean wasAddExecuted() { + + for (LensObjectDeltaOperation executedDeltaOperation : getExecutedDeltas()){ + ObjectDelta executedDelta = executedDeltaOperation.getObjectDelta(); + if (!executedDelta.isAdd()){ + continue; + } else if (executedDelta.getObjectToAdd() != null && executedDelta.getObjectTypeClass().equals(getObjectTypeClass())){ + return true; + } + } + + return false; + } + + abstract public ObjectDeltaObject getObjectDeltaObject() throws SchemaException; + + @Override + public String getOid() { + if (oid == null) { + oid = determineOid(); + } + return oid; + } + + public String determineOid() { + if (getObjectOld() != null && getObjectOld().getOid() != null) { + return getObjectOld().getOid(); + } + if (getObjectCurrent() != null && getObjectCurrent().getOid() != null) { + return getObjectCurrent().getOid(); + } + if (getObjectNew() != null && getObjectNew().getOid() != null) { + return getObjectNew().getOid(); + } + if (getPrimaryDelta() != null && getPrimaryDelta().getOid() != null) { + return getPrimaryDelta().getOid(); + } + if (getSecondaryDelta() != null && getSecondaryDelta().getOid() != null) { + return getSecondaryDelta().getOid(); + } + return null; + } + + /** + * Sets oid to the field but also to the deltas (if applicable). + */ + public void setOid(String oid) { + this.oid = oid; + if (primaryDelta != null && !primaryDelta.isImmutable()) { + primaryDelta.setOid(oid); + } + // TODO What if primary delta is immutable ADD delta and objectNew was taken from it? + // It would be immutable as well in that case. We will see. + if (objectNew != null) { + objectNew.setOid(oid); + } + } + + public PrismObjectDefinition getObjectDefinition() { + if (objectDefinition == null) { + if (objectOld != null) { + objectDefinition = objectOld.getDefinition(); + } else if (objectCurrent != null) { + objectDefinition = objectCurrent.getDefinition(); + } else if (objectNew != null) { + objectDefinition = objectNew.getDefinition(); + } else { + objectDefinition = getNotNullPrismContext().getSchemaRegistry().findObjectDefinitionByCompileTimeClass(getObjectTypeClass()); + } + } + return objectDefinition; + } + + public boolean isFresh() { + return isFresh; + } + + public void setFresh(boolean isFresh) { + this.isFresh = isFresh; + } + + @NotNull + public Collection getPolicyRules() { + return policyRules; + } + + public void addPolicyRule(EvaluatedPolicyRule policyRule) { + this.policyRules.add(policyRule); + } + + public void clearPolicyRules() { + policyRules.clear(); + } + + public void triggerRule(@NotNull EvaluatedPolicyRule rule, Collection> triggers) { + LensUtil.triggerRule(rule, triggers, policySituations); + } + + @NotNull + public Collection getPolicySituations() { + return policySituations; + } + + /** + * Returns security policy applicable to the object. This means security policy + * applicable directory to focus or projection. It will NOT return global + * security policy. + */ + public SecurityPolicyType getSecurityPolicy() { + return securityPolicy; + } + + public void setSecurityPolicy(SecurityPolicyType securityPolicy) { + this.securityPolicy = securityPolicy; + } + + public CredentialsPolicyType getCredentialsPolicy() { + return securityPolicy != null ? securityPolicy.getCredentials() : null; + } + + public void recompute() throws SchemaException, ConfigurationException { + PrismObject base = getObjectCurrentOrOld(); + ObjectDelta delta = getDelta(); + if (delta == null) { + // No change + objectNew = base; + return; + } + objectNew = delta.computeChangedObject(base); + } + + public void checkConsistence() { + checkConsistence(null); + } + + public void checkConsistence(String contextDesc) { + if (getObjectOld() != null) { + checkConsistence(getObjectOld(), "old "+getElementDesc() , contextDesc); + } + if (getObjectCurrent() != null) { + checkConsistence(getObjectCurrent(), "current "+getElementDesc() , contextDesc); + } + if (primaryDelta != null) { + checkConsistence(primaryDelta, false, getElementDesc()+" primary delta in "+this + (contextDesc == null ? "" : " in " +contextDesc)); + } + if (getObjectNew() != null) { + checkConsistence(getObjectNew(), "new "+getElementDesc(), contextDesc); + } + } + + protected void checkConsistence(ObjectDelta delta, boolean requireOid, String contextDesc) { + try { + delta.checkConsistence(requireOid, true, true, ConsistencyCheckScope.THOROUGH); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException(e.getMessage()+"; in "+contextDesc, e); + } catch (IllegalStateException e) { + throw new IllegalStateException(e.getMessage()+"; in "+contextDesc, e); + } + if (delta.isAdd()) { + checkConsistence(delta.getObjectToAdd(), "add object", contextDesc); + } + } + + protected boolean isRequireSecondaryDeltaOid() { + return primaryDelta == null; + } + + protected void checkConsistence(PrismObject object, String elementDesc, String contextDesc) { + String desc = elementDesc+" in "+this + (contextDesc == null ? "" : " in " +contextDesc); + try { + object.checkConsistence(true, ConsistencyCheckScope.THOROUGH); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException(e.getMessage()+"; in "+desc, e); + } catch (IllegalStateException e) { + throw new IllegalStateException(e.getMessage()+"; in "+desc, e); + } + if (object.getDefinition() == null) { + throw new IllegalStateException("No "+getElementDesc()+" definition "+desc); + } + O objectType = object.asObjectable(); + if (objectType instanceof ShadowType) { + ShadowUtil.checkConsistence((PrismObject) object, desc); + } + } + + /** + * Cleans up the contexts by removing some of the working state. + */ + public abstract void cleanup(); + + public void normalize() { + if (objectNew != null) { + objectNew.normalize(); + } + if (objectOld != null) { + objectOld.normalize(); + } + if (objectCurrent != null) { + objectCurrent.normalize(); + } + if (primaryDelta != null && !primaryDelta.isImmutable()) { + primaryDelta.normalize(); + } + } + + public void adopt(PrismContext prismContext) throws SchemaException { + if (objectNew != null) { + prismContext.adopt(objectNew); + } + if (objectOld != null) { + prismContext.adopt(objectOld); + } + if (objectCurrent != null) { + prismContext.adopt(objectCurrent); + } + if (primaryDelta != null) { + prismContext.adopt(primaryDelta); + } + // TODO: object definition? + } + + public abstract LensElementContext clone(LensContext lensContext); + + void copyValues(LensElementContext clone, LensContext lensContext) { + //noinspection unchecked + clone.lensContext = lensContext; + // This is de-facto immutable + clone.objectDefinition = this.objectDefinition; + clone.objectNew = cloneObject(this.objectNew); + clone.objectOld = cloneObject(this.objectOld); + clone.objectCurrent = cloneObject(this.objectCurrent); + clone.oid = this.oid; + clone.primaryDelta = cloneDelta(this.primaryDelta); + clone.isFresh = this.isFresh; + clone.iteration = this.iteration; + clone.iterationToken = this.iterationToken; + clone.securityPolicy = this.securityPolicy; + } + + protected ObjectDelta cloneDelta(ObjectDelta thisDelta) { + if (thisDelta == null) { + return null; + } + return thisDelta.clone(); + } + + private PrismObject cloneObject(PrismObject thisObject) { + if (thisObject == null) { + return null; + } + return thisObject.clone(); + } + + void storeIntoLensElementContextType(LensElementContextType lensElementContextType, LensContext.ExportType exportType) throws SchemaException { + if (objectOld != null && exportType != LensContext.ExportType.MINIMAL) { + if (exportType == LensContext.ExportType.REDUCED) { + lensElementContextType.setObjectOldRef(ObjectTypeUtil.createObjectRef(objectOld, getPrismContext())); + } else { + lensElementContextType.setObjectOld(objectOld.asObjectable().clone()); + } + } + if (objectCurrent != null && exportType == LensContext.ExportType.TRACE) { + lensElementContextType.setObjectCurrent(objectCurrent.asObjectable().clone()); + } + if (objectNew != null && exportType != LensContext.ExportType.MINIMAL) { + if (exportType == LensContext.ExportType.REDUCED) { + lensElementContextType.setObjectNewRef(ObjectTypeUtil.createObjectRef(objectNew, getPrismContext())); + } else { + lensElementContextType.setObjectNew(objectNew.asObjectable().clone()); + } + } + if (exportType != LensContext.ExportType.MINIMAL) { + lensElementContextType.setPrimaryDelta(primaryDelta != null ? DeltaConvertor.toObjectDeltaType(primaryDelta) : null); + for (LensObjectDeltaOperation executedDelta : executedDeltas) { + lensElementContextType.getExecutedDeltas() + .add(LensContext.simplifyExecutedDelta(executedDelta).toLensObjectDeltaOperationType()); + } + lensElementContextType.setObjectTypeClass(objectTypeClass.getName()); + lensElementContextType.setOid(oid); + lensElementContextType.setIteration(iteration); + lensElementContextType.setIterationToken(iterationToken); + lensElementContextType.setSynchronizationIntent( + synchronizationIntent != null ? synchronizationIntent.toSynchronizationIntentType() : null); + } + lensElementContextType.setFresh(isFresh); + } + + public void retrieveFromLensElementContextType(LensElementContextType lensElementContextType, Task task, OperationResult result) throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, ExpressionEvaluationException { + + ObjectType objectTypeOld = lensElementContextType.getObjectOld(); + this.objectOld = objectTypeOld != null ? (PrismObject) objectTypeOld.asPrismObject() : null; + fixProvisioningTypeInObject(this.objectOld, task, result); + + ObjectType objectTypeNew = lensElementContextType.getObjectNew(); + this.objectNew = objectTypeNew != null ? (PrismObject) objectTypeNew.asPrismObject() : null; + fixProvisioningTypeInObject(this.objectNew, task, result); + + ObjectType object = objectTypeNew != null ? objectTypeNew : objectTypeOld; + + ObjectDeltaType primaryDeltaType = lensElementContextType.getPrimaryDelta(); + this.primaryDelta = primaryDeltaType != null ? (ObjectDelta) DeltaConvertor.createObjectDelta(primaryDeltaType, lensContext.getPrismContext()) : null; + fixProvisioningTypeInDelta(this.primaryDelta, object, task, result); + + for (LensObjectDeltaOperationType eDeltaOperationType : lensElementContextType.getExecutedDeltas()) { + LensObjectDeltaOperation objectDeltaOperation = LensObjectDeltaOperation.fromLensObjectDeltaOperationType(eDeltaOperationType, lensContext.getPrismContext()); + if (objectDeltaOperation.getObjectDelta() != null) { + fixProvisioningTypeInDelta(objectDeltaOperation.getObjectDelta(), object, task, result); + } + this.executedDeltas.add(objectDeltaOperation); + } + + this.oid = lensElementContextType.getOid(); + + this.iteration = lensElementContextType.getIteration() != null ? lensElementContextType.getIteration() : 0; + this.iterationToken = lensElementContextType.getIterationToken(); + this.synchronizationIntent = SynchronizationIntent.fromSynchronizationIntentType(lensElementContextType.getSynchronizationIntent()); + + // note: objectTypeClass is already converted (used in the constructor) + } + + protected void fixProvisioningTypeInDelta(ObjectDelta delta, Objectable object, Task task, OperationResult result) { + if (delta != null && delta.getObjectTypeClass() != null && (ShadowType.class.isAssignableFrom(delta.getObjectTypeClass()) || ResourceType.class.isAssignableFrom(delta.getObjectTypeClass()))) { + try { + lensContext.getProvisioningService().applyDefinition(delta, object, task, result); + } catch (Exception e) { + LOGGER.warn("Error applying provisioning definitions to delta {}: {}", delta, e.getMessage()); + // In case of error just go on. Maybe we do not have correct definition here. But at least we can + // display the GUI pages and maybe we can also salvage the operation. + result.recordWarning(e); + } + } + } + + private void fixProvisioningTypeInObject(PrismObject object, Task task, OperationResult result) { + if (object != null && object.getCompileTimeClass() != null && (ShadowType.class.isAssignableFrom(object.getCompileTimeClass()) || ResourceType.class.isAssignableFrom(object.getCompileTimeClass()))) { + try { + lensContext.getProvisioningService().applyDefinition(object, task, result); + } catch (Exception e) { + LOGGER.warn("Error applying provisioning definitions to object {}: {}", object, e.getMessage()); + // In case of error just go on. Maybe we do not have correct definition here. But at least we can + // display the GUI pages and maybe we can also salvage the operation. + result.recordWarning(e); + } + } + } + + public void checkEncrypted() { + if (objectNew != null) { + CryptoUtil.checkEncrypted(objectNew); + } + if (objectOld != null) { + CryptoUtil.checkEncrypted(objectOld); + } + if (objectCurrent != null) { + CryptoUtil.checkEncrypted(objectCurrent); + } + if (primaryDelta != null) { + CryptoUtil.checkEncrypted(primaryDelta); + } + } + + public boolean operationMatches(ChangeTypeType operation) { + switch (operation) { + case ADD: + return getOperation() == SimpleOperationName.ADD; + case MODIFY: + return getOperation() == SimpleOperationName.MODIFY; + case DELETE: + return getOperation() == SimpleOperationName.DELETE; + } + throw new IllegalArgumentException("Unknown operation "+operation); + } + + protected abstract String getElementDefaultDesc(); + + protected String getElementDesc() { + PrismObject object = getObjectNew(); + if (object == null) { + object = getObjectOld(); + } + if (object == null) { + object = getObjectCurrent(); + } + if (object == null) { + return getElementDefaultDesc(); + } + return object.toDebugType(); + } + + protected String getDebugDumpTitle() { + return StringUtils.capitalize(getElementDesc()); + } + + protected String getDebugDumpTitle(String suffix) { + return getDebugDumpTitle()+" "+suffix; + } + + public abstract String getHumanReadableName(); + + public String getObjectReadVersion() { + // Do NOT use version from object current. + // Current object may be re-read, but the computation + // might be based on older data (objectOld). +// if (getObjectCurrent() != null) { +// return getObjectCurrent().getVersion(); +// } + if (getObjectOld() != null) { + return getObjectOld().getVersion(); + } + return null; + } + + public PrismObject getObjectCurrentOrOld() { + return objectCurrent != null ? objectCurrent : objectOld; + } + + @Override + public boolean isOfType(Class aClass) { + if (aClass.isAssignableFrom(objectTypeClass)) { + return true; + } + PrismObject object = getObjectAny(); + return object != null && aClass.isAssignableFrom(object.asObjectable().getClass()); + } + + public abstract void deleteSecondaryDeltas(); + + public S_ItemEntry deltaBuilder() throws SchemaException { + return getPrismContext().deltaFor(getObjectTypeClass()); + } + + public void forEachObject(Consumer> consumer) { + if (objectCurrent != null) { + consumer.accept(objectCurrent); + } + if (objectOld != null) { + consumer.accept(objectOld); + } + if (objectNew != null) { + consumer.accept(objectNew); + } + } + + public void forEachDelta(Consumer> consumer) { + if (primaryDelta != null) { + consumer.accept(primaryDelta); + } + } + + public void finishBuild() { + if (primaryDelta != null) { + primaryDelta.normalize(); + primaryDelta.freeze(); + } + } +} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensObjectDeltaOperation.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensObjectDeltaOperation.java index 254e6b7968e..bd7c4b7ca6e 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensObjectDeltaOperation.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensObjectDeltaOperation.java @@ -18,7 +18,6 @@ import org.jetbrains.annotations.NotNull; import java.io.Serializable; -import java.util.List; /** * @author semancik @@ -58,10 +57,14 @@ protected String getDebugDumpClassName() { return "LensObjectDeltaOperation"; } - @NotNull - public LensObjectDeltaOperationType toLensObjectDeltaOperationType() throws SchemaException { + @NotNull LensObjectDeltaOperationType toLensObjectDeltaOperationType() throws SchemaException { LensObjectDeltaOperationType retval = new LensObjectDeltaOperationType(); - retval.setObjectDeltaOperation(DeltaConvertor.toObjectDeltaOperationType(this, DeltaConversionOptions.createSerializeReferenceNames())); + DeltaConversionOptions options = DeltaConversionOptions.createSerializeReferenceNames(); + // Escaping invalid characters in serialized deltas could be questionable; see MID-6262. + // But because we currently do not use the deltas for other than human readers we can afford + // to replace invalid characters by descriptive text. + options.setEscapeInvalidCharacters(true); + retval.setObjectDeltaOperation(DeltaConvertor.toObjectDeltaOperationType(this, options)); retval.setAudited(audited); return retval; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ActionExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ActionExecutor.java index d48c07bf29e..7685634d2b1 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ActionExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ActionExecutor.java @@ -9,12 +9,11 @@ import com.evolveum.midpoint.model.api.ScriptExecutionException; import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; /** * Executes an action of a given type. Instances of this type must be registered with ScriptingExpressionEvaluator. - * - * @author mederly */ @FunctionalInterface public interface ActionExecutor { @@ -22,9 +21,18 @@ public interface ActionExecutor { /** * Executes given action command. * - * @param command - * @param context - * @param parentResult + * @param command Command to be executed. Its parameters can be defined statically (using "new" specific subclasses + * in the schema) or dynamically (using "old fashioned" dynamic name-value parameters) or in a mixed style, where + * dynamic definitions take precedence. + * + * @param input Input data (pipeline) that the action has to be executed on. + * + * @param context Overall execution context. + * + * @param globalResult Global operation result. This is the parent result that receives subresults related to + * actions executions. (But individual results are stored also into the pipeline, to indicate success/failure of + * individual pipeline items processing.) */ - PipelineData execute(ActionExpressionType command, PipelineData input, ExecutionContext context, OperationResult parentResult) throws ScriptExecutionException; + PipelineData execute(ActionExpressionType command, PipelineData input, ExecutionContext context, OperationResult globalResult) + throws ScriptExecutionException, SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/PipelineData.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/PipelineData.java index bdc692dfb22..ca2d4c432c1 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/PipelineData.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/PipelineData.java @@ -9,6 +9,7 @@ import com.evolveum.midpoint.model.api.PipelineItem; import com.evolveum.midpoint.model.api.ScriptExecutionException; +import com.evolveum.midpoint.model.impl.scripting.helpers.ScriptingDataUtil; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.schema.SearchResultList; @@ -20,6 +21,9 @@ import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.PipelineDataType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.PipelineItemType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ScriptingExpressionEvaluationOptionsType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ValueListType; import com.evolveum.prism.xml.ns._public.query_3.QueryType; import com.evolveum.prism.xml.ns._public.query_3.SearchFilterType; @@ -32,42 +36,40 @@ /** * Data that are passed between individual scripting actions. - * + *

* The content passed between actions (expressions) is a list of prism values - * (object, container, reference, property). - * - * @author mederly + * (object, container, reference, property) enriched with some additional information, + * see {@link PipelineItem}. */ public class PipelineData implements DebugDumpable { private static final String ITEM_OPERATION_NAME = ScriptingExpressionEvaluator.class.getName() + ".process"; - private final List data = new ArrayList<>(); // all items are not null + /** + * The data in the pipeline. All items are not null. + */ + @NotNull private final List data = new ArrayList<>(); // we want clients to use explicit constructors private PipelineData() { } - public List getData() { + public @NotNull List getData() { return data; } - @Override - public String debugDump(int indent) { - return DebugUtil.debugDump(data, indent); - } - - public static PipelineData create(PrismValue value) { - return create(value, VariablesMap.emptyMap()); - } - public static PipelineData create(PrismValue value, VariablesMap variables) { + public @NotNull static PipelineData create(@NotNull PrismValue value, @NotNull VariablesMap variables) { PipelineData d = createEmpty(); d.add(new PipelineItem(value, newOperationResult(), variables)); return d; } - public static OperationResult newOperationResult() { + public @NotNull static PipelineData createEmpty() { + return new PipelineData(); + } + + public @NotNull static OperationResult newOperationResult() { return new OperationResult(ITEM_OPERATION_NAME); } @@ -75,10 +77,6 @@ public void add(@NotNull PipelineItem pipelineItem) { data.add(pipelineItem); } - public static PipelineData createEmpty() { - return new PipelineData(); - } - public void addAllFrom(PipelineData otherData) { if (otherData != null) { data.addAll(otherData.getData()); @@ -95,39 +93,38 @@ public void addValue(PrismValue value, OperationResult result, VariablesMap vari variables != null ? variables : VariablesMap.emptyMap())); } - public String getDataAsSingleString() throws ScriptExecutionException { - if (!data.isEmpty()) { - if (data.size() == 1) { - return (String) ((PrismPropertyValue) data.get(0).getValue()).getRealValue(); // todo implement some diagnostics when this would fail - } else { - throw new ScriptExecutionException("Multiple values where just one is expected"); - } - } else { + public T getSingleValue(Class clazz) throws SchemaException { + if (data.isEmpty()) { return null; + } else if (data.size() == 1) { + return ScriptingDataUtil.getRealValue(data.get(0).getValue(), clazz); + } else { + throw new SchemaException("Multiple values where just one is expected"); } } - static PipelineData createItem(@NotNull PrismValue value, VariablesMap variables) throws SchemaException { - PipelineData data = createEmpty(); - data.addValue(value, variables); - return data; - } - - public Collection getDataAsReferences(QName defaultTargetType, Class typeForQuery, + /** + * Returns the pipeline content as a list of references. Objects, PRVs, OIDs are converted directly + * to references. Search filters and queries are evaluated first. + * + * This is a legacy method and its use should be avoided. + */ + @NotNull + public List getDataAsReferences(QName defaultTargetType, Class typeForQuery, ExecutionContext context, OperationResult result) throws ScriptExecutionException, CommunicationException, ObjectNotFoundException, SchemaException, SecurityViolationException, ConfigurationException, ExpressionEvaluationException { - Collection retval = new ArrayList<>(data.size()); + List retval = new ArrayList<>(data.size()); for (PipelineItem item : data) { PrismValue value = item.getValue(); if (value instanceof PrismObjectValue) { - PrismObjectValue objectValue = (PrismObjectValue) value; + PrismObjectValue objectValue = (PrismObjectValue) value; ObjectReferenceType ref = new ObjectReferenceType(); - ref.setType(objectValue.asPrismObject().getDefinition().getTypeName()); // todo check the definition is present - ref.setOid(objectValue.getOid()); // todo check if oid is present + ref.setType(objectValue.asPrismObject().getDefinition().getTypeName()); + ref.setOid(objectValue.getOid()); retval.add(ref); } else if (value instanceof PrismPropertyValue) { - Object realValue = ((PrismPropertyValue) value).getRealValue(); + Object realValue = value.getRealValue(); if (realValue instanceof SearchFilterType) { retval.addAll( resolveQuery( @@ -138,7 +135,7 @@ public Collection getDataAsReferences(QName defaultTargetTy } else if (realValue instanceof String) { ObjectReferenceType ref = new ObjectReferenceType(); ref.setType(defaultTargetType); - ref.setOid((String) realValue); // todo implement search by name + ref.setOid((String) realValue); retval.add(ref); } else if (realValue instanceof ObjectReferenceType) { retval.add((ObjectReferenceType) realValue); @@ -165,7 +162,7 @@ private Collection resolveQuery(Class return objects.stream().map(o -> ObjectTypeUtil.createObjectRef(o, context.getPrismContext())).collect(Collectors.toList()); } - static PipelineData parseFrom(ValueListType input, VariablesMap frozenInitialVariables, PrismContext prismContext) { + static @NotNull PipelineData parseFrom(ValueListType input, VariablesMap frozenInitialVariables, PrismContext prismContext) { PipelineData rv = new PipelineData(); if (input != null) { for (Object o : input.getValue()) { @@ -193,9 +190,39 @@ static PipelineData parseFrom(ValueListType input, VariablesMap frozenInitialVar return rv; } - public PipelineData cloneMutableState() { + PipelineData cloneMutableState() { PipelineData rv = new PipelineData(); data.forEach(d -> rv.add(d.cloneMutableState())); return rv; } + + @Override + public String debugDump(int indent) { + return DebugUtil.debugDump(data, indent); + } + + public static PipelineDataType prepareXmlData( + List output, ScriptingExpressionEvaluationOptionsType options) { + boolean hideResults = options != null && Boolean.TRUE.equals(options.isHideOperationResults()); + PipelineDataType rv = new PipelineDataType(); + if (output != null) { + for (PipelineItem item : output) { + PipelineItemType itemType = new PipelineItemType(); + PrismValue value = item.getValue(); + if (value instanceof PrismReferenceValue) { + // This is a bit of hack: value.getRealValue() would return unserializable object (PRV$1 - does not have type QName) + ObjectReferenceType ort = new ObjectReferenceType(); + ort.setupReferenceValue((PrismReferenceValue) value); + itemType.setValue(ort); + } else { + itemType.setValue(value.getRealValue()); + } + if (!hideResults) { + itemType.setResult(item.getResult().createOperationResultType()); + } + rv.getItem().add(itemType); + } + } + return rv; + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ScriptingActionExecutorRegistry.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ScriptingActionExecutorRegistry.java new file mode 100644 index 00000000000..aeaea8b3504 --- /dev/null +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ScriptingActionExecutorRegistry.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.model.impl.scripting; + +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; + +import org.jetbrains.annotations.NotNull; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * + */ +@Component +public class ScriptingActionExecutorRegistry { + + private final Map executorsByTypeName = new ConcurrentHashMap<>(); + private final Map, ActionExecutor> executorsByBeanClass = new ConcurrentHashMap<>(); + + public void register(String name, Class type, ActionExecutor executor) { + executorsByTypeName.put(name, executor); + executorsByBeanClass.put(type, executor); + } + + public void register(String name, ActionExecutor executor) { + executorsByTypeName.put(name, executor); + } + + @NotNull ActionExecutor getExecutor(ActionExpressionType action) { + if (action.getType() != null) { + ActionExecutor executor = executorsByTypeName.get(action.getType()); + if (executor != null) { + return executor; + } else { + throw new IllegalStateException("Unknown action executor for action type '" + action.getType() + "'"); + } + } else { + ActionExecutor executor = executorsByBeanClass.get(action.getClass()); + if (executor != null) { + return executor; + } else { + throw new IllegalStateException("Unknown action executor for bean class '" + action.getClass().getName() + "'"); + } + } + } +} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ScriptingExpressionEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ScriptingExpressionEvaluator.java index 6c541809139..e38d366093a 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ScriptingExpressionEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ScriptingExpressionEvaluator.java @@ -14,9 +14,8 @@ import com.evolveum.midpoint.model.impl.scripting.expressions.FilterContentEvaluator; import com.evolveum.midpoint.model.impl.scripting.expressions.SearchEvaluator; import com.evolveum.midpoint.model.impl.scripting.expressions.SelectEvaluator; -import com.evolveum.midpoint.model.impl.scripting.helpers.ScriptingJaxbUtil; +import com.evolveum.midpoint.model.impl.scripting.helpers.ScriptingBeansUtil; import com.evolveum.midpoint.prism.*; -import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.repo.common.expression.ExpressionFactory; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.expression.ExpressionProfile; @@ -42,15 +41,12 @@ import org.springframework.stereotype.Component; import javax.xml.bind.JAXBElement; -import javax.xml.namespace.QName; -import java.util.HashMap; import java.util.List; -import java.util.Map; + +import static com.evolveum.midpoint.model.impl.scripting.helpers.ScriptingBeansUtil.getActionType; /** * Main entry point for evaluating scripting expressions. - * - * @author mederly */ @Component public class ScriptingExpressionEvaluator { @@ -66,15 +62,12 @@ public class ScriptingExpressionEvaluator { @Autowired private PrismContext prismContext; @Autowired private ModelObjectResolver modelObjectResolver; @Autowired private ExpressionFactory expressionFactory; - - private ObjectFactory objectFactory = new ObjectFactory(); - - private Map actionExecutors = new HashMap<>(); + @Autowired public ScriptingActionExecutorRegistry actionExecutorRegistry; // TODO implement more nicely public static ExecuteScriptType createExecuteScriptCommand(ScriptingExpressionType expression) { ExecuteScriptType executeScriptCommand = new ExecuteScriptType(); - executeScriptCommand.setScriptingExpression(ScriptingJaxbUtil.toJaxbElement(expression)); + executeScriptCommand.setScriptingExpression(ScriptingBeansUtil.toJaxbElement(expression)); return executeScriptCommand; } @@ -170,12 +163,18 @@ private ExecutionContext evaluateExpression(@NotNull ExecuteScriptType executeSc } // not to be called from outside - public PipelineData evaluateExpression(JAXBElement expression, PipelineData input, ExecutionContext context, OperationResult parentResult) throws ScriptExecutionException { + public PipelineData evaluateExpression(JAXBElement expression, PipelineData input, + ExecutionContext context, OperationResult parentResult) throws ScriptExecutionException, SchemaException, + ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, + ExpressionEvaluationException { return evaluateExpression(expression.getValue(), input, context, parentResult); } // not to be called from outside - public PipelineData evaluateExpression(ScriptingExpressionType value, PipelineData input, ExecutionContext context, OperationResult parentResult) throws ScriptExecutionException { + public PipelineData evaluateExpression(ScriptingExpressionType value, PipelineData input, ExecutionContext context, + OperationResult parentResult) + throws ScriptExecutionException, SchemaException, ConfigurationException, ObjectNotFoundException, + CommunicationException, SecurityViolationException, ExpressionEvaluationException { context.checkTaskStop(); OperationResult globalResult = parentResult.createMinorSubresult(DOT_CLASS + "evaluateExpression"); PipelineData output; @@ -195,37 +194,35 @@ public PipelineData evaluateExpression(ScriptingExpressionType value, PipelineDa throw new IllegalArgumentException("Unsupported expression type: " + (value==null?"(null)":value.getClass())); } globalResult.computeStatusIfUnknown(); + globalResult.setSummarizeSuccesses(true); + globalResult.summarize(); return output; } - private PipelineData executeAction(ActionExpressionType command, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { - Validate.notNull(command, "command"); - Validate.notNull(command.getType(), "command.actionType"); - + private PipelineData executeAction(@NotNull ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException, SchemaException, ObjectNotFoundException, + SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Executing action {} on {}", command.getType(), input.debugDump()); + LOGGER.trace("Executing action {} on {}", getActionType(action), input.debugDump()); } else if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Executing action {}", command.getType()); - } - ActionExecutor executor = actionExecutors.get(command.getType()); - if (executor == null) { - throw new IllegalStateException("Unsupported action type: " + command.getType()); - } else { - PipelineData retval = executor.execute(command, input, context, globalResult); - globalResult.setSummarizeSuccesses(true); - globalResult.summarize(); - return retval; + LOGGER.debug("Executing action {}", getActionType(action)); } + return actionExecutorRegistry.getExecutor(action) + .execute(action, input, context, globalResult); } - private PipelineData executePipeline(ExpressionPipelineType pipeline, PipelineData data, ExecutionContext context, OperationResult result) throws ScriptExecutionException { + private PipelineData executePipeline(ExpressionPipelineType pipeline, PipelineData data, ExecutionContext context, + OperationResult result) throws ScriptExecutionException, SchemaException, ConfigurationException, + ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException { for (JAXBElement expressionType : pipeline.getScriptingExpression()) { data = evaluateExpression(expressionType, data, context, result); } return data; } - private PipelineData executeSequence(ExpressionSequenceType sequence, PipelineData input, ExecutionContext context, OperationResult result) throws ScriptExecutionException { + private PipelineData executeSequence(ExpressionSequenceType sequence, PipelineData input, ExecutionContext context, + OperationResult result) throws ScriptExecutionException, SchemaException, ConfigurationException, + ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException { PipelineData lastOutput = null; List> scriptingExpression = sequence.getScriptingExpression(); for (int i = 0; i < scriptingExpression.size(); i++) { @@ -236,7 +233,7 @@ private PipelineData executeSequence(ExpressionSequenceType sequence, PipelineDa return lastOutput; } - public PipelineData evaluateConstantExpression(@NotNull RawType constant, @Nullable Class expectedClass, ExecutionContext context, String desc, OperationResult result) throws ScriptExecutionException { + public PipelineData evaluateConstantExpression(@NotNull RawType constant, @Nullable Class expectedClass, ExecutionContext context, String desc) throws ScriptExecutionException { try { // TODO fix this brutal hacking @@ -256,25 +253,21 @@ public PipelineData evaluateConstantExpression(@NotNull RawType constant, @Nulla if (value.isRaw()) { throw new IllegalStateException("Raw value while " + desc + ": " + value + ". Please specify type of the value."); } - return PipelineData.createItem(value, context.getInitialVariables()); + return PipelineData.create(value, context.getInitialVariables()); } catch (SchemaException e) { throw new ScriptExecutionException(e.getMessage(), e); } } - public PipelineData evaluateConstantStringExpression(RawType constant, ExecutionContext context, OperationResult result) throws ScriptExecutionException { + public PipelineData evaluateConstantStringExpression(RawType constant, ExecutionContext context) throws ScriptExecutionException { try { String value = constant.getParsedRealValue(String.class); - return PipelineData.createItem(prismContext.itemFactory().createPropertyValue(value), context.getInitialVariables()); + return PipelineData.create(prismContext.itemFactory().createPropertyValue(value), context.getInitialVariables()); } catch (SchemaException e) { throw new ScriptExecutionException(e.getMessage(), e); } } - public void registerActionExecutor(String actionName, ActionExecutor executor) { - actionExecutors.put(actionName, executor); - } - ModelService getModelService() { return modelService; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/AbstractObjectBasedActionExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/AbstractObjectBasedActionExecutor.java new file mode 100644 index 00000000000..a0c21e724a2 --- /dev/null +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/AbstractObjectBasedActionExecutor.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.model.impl.scripting.actions; + +import com.evolveum.midpoint.model.api.PipelineItem; +import com.evolveum.midpoint.model.api.ScriptExecutionException; +import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; +import com.evolveum.midpoint.model.impl.scripting.PipelineData; +import com.evolveum.midpoint.prism.Objectable; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismObjectValue; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.exception.CommonException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; + +import org.jetbrains.annotations.NotNull; + +/** + * Action executor that can iterates over set of PrismObjects of a specified (expected) type. + */ +abstract class AbstractObjectBasedActionExecutor extends BaseActionExecutor { + + @FunctionalInterface + public interface ObjectProcessor { + void process(PrismObject object, PipelineItem item, OperationResult result) throws ScriptExecutionException, CommonException; + } + + @FunctionalInterface + public interface ConsoleFailureMessageWriter { + void write(PrismObject object, @NotNull Throwable exception); + } + + abstract Class getObjectType(); + + void iterateOverObjects(PipelineData input, ExecutionContext context, OperationResult globalResult, + ObjectProcessor consumer, ConsoleFailureMessageWriter writer) + throws ScriptExecutionException { + for (PipelineItem item: input.getData()) { + PrismValue value = item.getValue(); + OperationResult result = operationsHelper.createActionResult(item, this); + try { + context.checkTaskStop(); + PrismObject object = castToObject(value, getObjectType(), context); + if (object != null) { + T objectable = object.asObjectable(); + long started = operationsHelper.recordStart(context, objectable); + try { + consumer.process(object, item, result); + operationsHelper.recordEnd(context, objectable, started, null); + } catch (Throwable e) { + operationsHelper.recordEnd(context, objectable, started, e); + Throwable exception = processActionException(e, getActionName(), value, context); + writer.write(object, exception); + } + } + operationsHelper.trimAndCloneResult(result, globalResult); + } catch (Throwable t) { + result.recordFatalError(t); + throw t; + } finally { + result.computeStatusIfUnknown(); // just in case (should be already computed) + } + } + } + + @SuppressWarnings("ThrowableNotThrown") + private PrismObject castToObject(PrismValue value, Class expectedType, ExecutionContext context) + throws ScriptExecutionException { + if (value instanceof PrismObjectValue) { + PrismObjectValue objectValue = (PrismObjectValue) value; + Class realType = objectValue.asObjectable().getClass(); + if (expectedType.isAssignableFrom(realType)) { + //noinspection unchecked + return objectValue.asPrismObject(); + } else { + processActionException(new ScriptExecutionException("Item is not a PrismObject of " + expectedType.getName() + + "; it is " + realType.getName() + " instead"), getActionName(), value, context); + return null; + } + } else { + processActionException(new ScriptExecutionException("Item is not a PrismObject"), getActionName(), value, context); + return null; + } + } +} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/AddExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/AddExecutor.java index 53a949cfca0..f686bb67fe1 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/AddExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/AddExecutor.java @@ -11,18 +11,16 @@ import com.evolveum.midpoint.model.api.ScriptExecutionException; import com.evolveum.midpoint.model.impl.scripting.PipelineData; import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; -import com.evolveum.midpoint.model.api.PipelineItem; -import com.evolveum.midpoint.model.impl.scripting.helpers.OperationsHelper; import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectValue; -import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.prism.delta.DeltaFactory; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.schema.ObjectDeltaOperation; import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; -import org.springframework.beans.factory.annotation.Autowired; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.AddActionExpressionType; + import org.springframework.stereotype.Component; import java.util.Collection; @@ -30,56 +28,54 @@ import javax.annotation.PostConstruct; /** - * @author mederly + * */ @Component -public class AddExecutor extends BaseActionExecutor { +public class AddExecutor extends AbstractObjectBasedActionExecutor { private static final String NAME = "add"; - @Autowired private OperationsHelper operationsHelper; - @PostConstruct public void init() { - scriptingExpressionEvaluator.registerActionExecutor(NAME, this); + actionExecutorRegistry.register(NAME, AddActionExpressionType.class, this); } @Override - public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { + public PipelineData execute(ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException, SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { - ModelExecuteOptions executionOptions = getOptions(expression, input, context, globalResult); - boolean dryRun = getParamDryRun(expression, input, context, globalResult); + ModelExecuteOptions options = operationsHelper.getOptions(action, input, context, globalResult); + boolean dryRun = operationsHelper.getDryRun(action, input, context, globalResult); + + iterateOverObjects(input, context, globalResult, + (object, item, result) -> + add(object, dryRun, options, context, result), + (object, exception) -> + context.println("Failed to add " + object + drySuffix(dryRun) + exceptionSuffix(exception)) + ); - for (PipelineItem item : input.getData()) { - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); - context.checkTaskStop(); - PrismValue value = item.getValue(); - if (value instanceof PrismObjectValue) { - @SuppressWarnings({ "unchecked", "raw" }) - PrismObject prismObject = ((PrismObjectValue) value).asPrismObject(); - ObjectType objectType = prismObject.asObjectable(); - long started = operationsHelper.recordStart(context, objectType); - Throwable exception = null; - try { - Collection> executedDeltas = operationsHelper.applyDelta(createAddDelta(objectType), executionOptions, dryRun, context, result); - String newObjectOid = ObjectDeltaOperation.findAddDeltaOid(executedDeltas, prismObject); - prismObject.setOid(newObjectOid); - operationsHelper.recordEnd(context, objectType, started, null); - } catch (Throwable ex) { - operationsHelper.recordEnd(context, objectType, started, ex); - exception = processActionException(ex, NAME, value, context); - } - context.println((exception != null ? "Attempted to add " : "Added ") + prismObject.toString() + optionsSuffix(executionOptions, dryRun) + exceptionSuffix(exception)); - } else { - //noinspection ThrowableNotThrown - processActionException(new ScriptExecutionException("Item is not a PrismObject"), NAME, value, context); - } - operationsHelper.trimAndCloneResult(result, globalResult, context); - } return input; } - private ObjectDelta createAddDelta(ObjectType objectType) { - return DeltaFactory.Object.createAddDelta(objectType.asPrismObject()); + private void add(PrismObject object, boolean dryRun, ModelExecuteOptions options, ExecutionContext context, + OperationResult result) throws ScriptExecutionException { + ObjectDelta addDelta = DeltaFactory.Object.createAddDelta(object); + Collection> executedDeltas = + operationsHelper.applyDelta(addDelta, options, dryRun, context, result); + if (executedDeltas != null) { + String newObjectOid = ObjectDeltaOperation.findAddDeltaOid(executedDeltas, object); + object.setOid(newObjectOid); + } + context.println("Added " + object + drySuffix(dryRun)); + } + + @Override + Class getObjectType() { + return ObjectType.class; + } + + @Override + String getActionName() { + return NAME; } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ApplyDefinitionExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ApplyDefinitionExecutor.java index b83af72f78e..45b5c2a7d2e 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ApplyDefinitionExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ApplyDefinitionExecutor.java @@ -7,64 +7,65 @@ package com.evolveum.midpoint.model.impl.scripting.actions; -import com.evolveum.midpoint.model.api.PipelineItem; import com.evolveum.midpoint.model.api.ScriptExecutionException; import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; import com.evolveum.midpoint.model.impl.scripting.PipelineData; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectValue; -import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ApplyDefinitionActionExpressionType; + import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; /** - * @author mederly + * Applies definitions to relevant objects. Currently supports ShadowType and ResourceType + * that are given definitions by provisioning module. */ @Component -public class ApplyDefinitionExecutor extends BaseActionExecutor { - - //private static final Trace LOGGER = TraceManager.getTrace(ReencryptExecutor.class); +public class ApplyDefinitionExecutor extends AbstractObjectBasedActionExecutor { private static final String NAME = "apply-definition"; @PostConstruct public void init() { - scriptingExpressionEvaluator.registerActionExecutor(NAME, this); + actionExecutorRegistry.register(NAME, ApplyDefinitionActionExpressionType.class, this); } @Override - public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { + public PipelineData execute(ActionExpressionType expression, PipelineData input, + ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { + + iterateOverObjects(input, context, globalResult, + (object, item, result) -> + applyDefinition(object.asObjectable(), context, result), + (object, exception) -> + context.println("Failed to apply definition to " + object + exceptionSuffix(exception)) + ); - for (PipelineItem item: input.getData()) { - PrismValue value = item.getValue(); - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); - context.checkTaskStop(); - if (value instanceof PrismObjectValue) { - @SuppressWarnings({"unchecked", "raw"}) - PrismObject prismObject = ((PrismObjectValue) value).asPrismObject(); - ObjectType objectBean = prismObject.asObjectable(); - if (objectBean instanceof ShadowType || objectBean instanceof ResourceType) { - try { - provisioningService.applyDefinition(prismObject, context.getTask(), result); - result.computeStatus(); - } catch (Throwable ex) { - result.recordFatalError("Couldn't reencrypt object", ex); - Throwable exception = processActionException(ex, NAME, value, context); - context.println("Couldn't apply definition to " + prismObject.toString() + exceptionSuffix(exception)); - } - } - } else { - //noinspection ThrowableNotThrown - processActionException(new ScriptExecutionException("Item is not a PrismObject"), NAME, value, context); - } - operationsHelper.trimAndCloneResult(result, globalResult, context); - } return input; } + + private void applyDefinition(ObjectType object, ExecutionContext context, OperationResult result) + throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException, + ExpressionEvaluationException { + if (object instanceof ShadowType || object instanceof ResourceType) { + provisioningService.applyDefinition(object.asPrismObject(), context.getTask(), result); + context.println("Applied definition to " + object); + } + } + + @Override + protected Class getObjectType() { + return ObjectType.class; + } + + @Override + protected String getActionName() { + return NAME; + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/AssignExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/AssignExecutor.java index 8a7bd222731..11a9f9de440 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/AssignExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/AssignExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2014 Evolveum and contributors + * Copyright (c) 2020 Evolveum and contributors * * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. @@ -10,31 +10,70 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; +import javax.annotation.PostConstruct; import javax.xml.namespace.QName; -import org.springframework.beans.factory.annotation.Autowired; +import com.evolveum.midpoint.model.api.ScriptExecutionException; +import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; +import com.evolveum.midpoint.model.impl.scripting.PipelineData; +import com.evolveum.midpoint.prism.query.ObjectQuery; +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.exception.*; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; + +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.AssignActionExpressionType; + import org.springframework.stereotype.Component; import com.evolveum.midpoint.prism.PrismConstants; import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.schema.RelationRegistry; import com.evolveum.midpoint.util.MiscUtil; -import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import static com.evolveum.midpoint.model.impl.scripting.actions.AssignExecutor.*; + +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; + @Component -public class AssignExecutor extends AssignmentOperationsExecutor { +public class AssignExecutor extends AssignmentOperationsExecutor { - @Autowired protected RelationRegistry relationRegistry; + private static final Trace LOGGER = TraceManager.getTrace(AssignExecutor.class); - @Override - protected String getName() { - return AssignmentOperationsExecutor.ASSIGN_NAME; + private static final String NAME = "assign"; + + /** + * These are "purified" parameters: targets and constructions to assign. + * They are created by merging dynamically and statically defined parameters, resolving + * filters in references, and so on. + */ + static class AssignParameters extends AssignmentOperationsExecutor.Parameters { + private final List targetRefs = new ArrayList<>(); + private final List constructions = new ArrayList<>(); + } + + @PostConstruct + public void init() { + actionExecutorRegistry.register(NAME, AssignActionExpressionType.class, this); } @Override - protected ObjectDelta createDelta(AssignmentHolderType object, Collection resources, - Collection roles, Collection relationSpecifications) throws SchemaException { + AssignParameters parseParameters(ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult result) throws SchemaException, ScriptExecutionException, ObjectNotFoundException, + SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { + + AssignParameters parameters = new AssignParameters(); + + // Dynamic parameters + + Collection dynamicRoleRefs = getRolesParameter(action, input, context, result); + Collection dynamicResourceRefs = getResourcesParameter(action, input, context, result); + Collection relationSpecifications = getRelationsParameter(action, input, context, result); QName relationSpecification = MiscUtil.extractSingleton(relationSpecifications, () -> new IllegalArgumentException("Using 'relation' as a multivalued parameter is not allowed")); @@ -43,36 +82,134 @@ protected ObjectDelta createDelta(AssignmentHolderType obj throw new IllegalArgumentException("Using 'q:any' as relation specification is not allowed"); } - List assignmentsToAdd = new ArrayList<>(); - - if (roles != null) { + QName relationOverride; + if (relationSpecification != null) { List relationDefinitions = relationRegistry.getRelationDefinitions(); - QName matchingRelation = relationDefinitions.stream() + relationOverride = relationDefinitions.stream() .filter(definition -> prismContext.relationMatches(relationSpecification, definition.getRef())) .findFirst() .orElseThrow(() -> new IllegalArgumentException("Relation matching '" + relationSpecification + "' not found")) .getRef(); - for (ObjectReferenceType roleRef : roles) { - assignmentsToAdd.add( - new AssignmentType(prismContext) - .targetRef(roleRef.clone() - .relation(matchingRelation))); - } + } else { + relationOverride = null; + } + + // Static parameters + + Collection staticTargetRefs; + Collection staticResourceRefs; + Collection staticConstructions; + if (action instanceof AssignActionExpressionType) { + staticTargetRefs = ((AssignActionExpressionType) action).getTargetRef(); + staticResourceRefs = ((AssignActionExpressionType) action).getResourceRef(); + staticConstructions = ((AssignActionExpressionType) action).getConstruction(); + } else { + staticTargetRefs = emptyList(); + staticResourceRefs = emptyList(); + staticConstructions = emptyList(); } - if (resources != null) { - for (ObjectReferenceType resourceRef : resources) { - assignmentsToAdd.add( - new AssignmentType(prismContext) - .beginConstruction() - .resourceRef(resourceRef) // relation is ignored here - .end()); + // Consolidation + + Task task = context.getTask(); + + parameters.targetRefs.addAll(resolve(staticTargetRefs, relationOverride, task, result)); + parameters.targetRefs.addAll(resolve(dynamicRoleRefs, relationOverride, task, result)); + + QName defaultRelation = relationRegistry.getDefaultRelation(); + parameters.constructions.addAll(staticConstructions); + parameters.constructions.addAll(resourceRefsToConstructions(resolve(staticResourceRefs, defaultRelation, task, result))); + parameters.constructions.addAll(resourceRefsToConstructions(resolve(dynamicResourceRefs, defaultRelation, task, result))); + + return parameters; + } + + @Override + boolean checkParameters(AssignParameters parameters, ExecutionContext context) { + if (parameters.targetRefs.isEmpty() && parameters.constructions.isEmpty()) { + LOGGER.warn("There are no targets nor constructions to assign"); + context.println("Warning: There are no targets nor constructions to assign"); + return false; + } else { + return true; + } + } + + private Collection resolve(Collection targetRefs, QName relationOverride, Task task, + OperationResult result) throws SchemaException, ObjectNotFoundException, SecurityViolationException, + CommunicationException, ConfigurationException, ExpressionEvaluationException { + Collection rv = new ArrayList<>(); + for (ObjectReferenceType ref : targetRefs) { + rv.addAll(resolve(ref, relationOverride, task, result)); + } + return rv; + } + + private Collection resolve(ObjectReferenceType ref, QName relationOverride, Task task, OperationResult result) + throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, + SecurityViolationException, ExpressionEvaluationException { + if (ref.getFilter() != null) { + Class clazz = prismContext.getSchemaRegistry().determineCompileTimeClass(ref.getType()); + if (clazz == null) { + throw new SchemaException("No compile time class for " + ref.getType() + " in " + ref); } + ObjectQuery query = prismContext.getQueryConverter().createObjectQuery(clazz, ref.getFilter()); + QName effectiveRelation = getEffectiveRelation(ref, relationOverride); + return modelService.searchObjects(clazz, query, null, task, result).stream() + .map(object -> ObjectTypeUtil.createObjectRef(object, effectiveRelation)) + .collect(Collectors.toList()); + } else if (relationOverride != null) { + return singletonList(ref.clone().relation(relationOverride)); + } else { + return singletonList(ref); } + } + + private QName getEffectiveRelation(ObjectReferenceType reference, QName relationOverride) { + QName effectiveRelation; + if (relationOverride != null) { + effectiveRelation = relationOverride; + } else if (reference.getRelation() != null) { + effectiveRelation = reference.getRelation(); + } else { + effectiveRelation = relationRegistry.getDefaultRelation(); + } + return effectiveRelation; + } + + private Collection resourceRefsToConstructions(Collection resourceRefs) { + return resourceRefs.stream() + .map(ref -> new ConstructionType(prismContext).resourceRef(ref.clone())) + .collect(Collectors.toList()); + } + + private Collection targetsToAssignments(Collection targetRefs) { + return targetRefs.stream() + .map(ref -> new AssignmentType(prismContext).targetRef(ref.clone())) + .collect(Collectors.toList()); + } + + private Collection constructionsToAssignments(Collection constructions) { + return constructions.stream() + .map(c -> new AssignmentType(prismContext).construction(c.clone())) + .collect(Collectors.toList()); + } + + @Override + protected ObjectDelta createDelta(AssignmentHolderType object, AssignParameters parameters) throws SchemaException { + + List assignmentsToAdd = new ArrayList<>(); + assignmentsToAdd.addAll(targetsToAssignments(parameters.targetRefs)); + assignmentsToAdd.addAll(constructionsToAssignments(parameters.constructions)); return prismContext.deltaFor(object.getClass()) .item(AssignmentHolderType.F_ASSIGNMENT) - .addRealValues(assignmentsToAdd) + .addRealValues(assignmentsToAdd) .asObjectDelta(object.getOid()); } + + @Override + protected String getActionName() { + return NAME; + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/AssignmentOperationsExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/AssignmentOperationsExecutor.java index 46870243902..472fe46f004 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/AssignmentOperationsExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/AssignmentOperationsExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2019 Evolveum and contributors + * Copyright (c) 2020 Evolveum and contributors * * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. @@ -7,146 +7,119 @@ package com.evolveum.midpoint.model.impl.scripting.actions; +import java.util.Collection; +import java.util.Collections; +import java.util.stream.Collectors; +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.util.exception.*; + import com.evolveum.midpoint.model.api.ModelExecuteOptions; -import com.evolveum.midpoint.model.api.PipelineItem; import com.evolveum.midpoint.model.api.ScriptExecutionException; import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; import com.evolveum.midpoint.model.impl.scripting.PipelineData; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectValue; -import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.schema.constants.RelationTypes; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.util.QNameUtil; -import com.evolveum.midpoint.util.exception.CommonException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionParameterValueType; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.ObjectUtils; -import org.jetbrains.annotations.NotNull; - -import javax.annotation.PostConstruct; -import javax.xml.namespace.QName; -import java.util.Collection; -import java.util.Collections; -import java.util.stream.Collectors; +import org.jetbrains.annotations.NotNull; /** - * + * Abstract executor for assign and unassign actions. */ -public abstract class AssignmentOperationsExecutor extends BaseActionExecutor { +abstract class AssignmentOperationsExecutor

+ extends AbstractObjectBasedActionExecutor { - private static final Trace LOGGER = TraceManager.getTrace(AssignmentOperationsExecutor.class); - - static final String UNASSIGN_NAME = "unassign"; - static final String ASSIGN_NAME = "assign"; private static final String PARAM_RESOURCE = "resource"; private static final String PARAM_ROLE = "role"; private static final String PARAM_RELATION = "relation"; - @PostConstruct - public void init() { - scriptingExpressionEvaluator.registerActionExecutor(getName(), this); + static class Parameters { + ModelExecuteOptions options; + boolean dryRun; } - protected abstract String getName(); - @Override - public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { + public PipelineData execute(ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException, SchemaException, ConfigurationException, + ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException { + + P parameters = parseParameters(action, input, context, globalResult); + parameters.options = operationsHelper.getOptions(action, input, context, globalResult); + parameters.dryRun = operationsHelper.getDryRun(action, input, context, globalResult); + + if (checkParameters(parameters, context)) { + iterateOverObjects(input, context, globalResult, + (object, item, result) -> + apply(object.asObjectable(), parameters, context, result), + (object, exception) -> + context.println("Failed to modify " + object + drySuffix(parameters.dryRun) + exceptionSuffix(exception)) + ); + } - ModelExecuteOptions executionOptions = getOptions(expression, input, context, globalResult); - boolean dryRun = getParamDryRun(expression, input, context, globalResult); + return input; + } - ActionParameterValueType resourceParameterValue = expressionHelper.getArgument(expression.getParameter(), PARAM_RESOURCE, false, false, getName()); - ActionParameterValueType roleParameterValue = expressionHelper.getArgument(expression.getParameter(), PARAM_ROLE, false, false, getName()); - Collection relationSpecificationUris = expressionHelper.getArgumentValues(expression.getParameter(), PARAM_RELATION, false, false, getName(), input, context, String.class, globalResult); + abstract boolean checkParameters(P parameters, ExecutionContext context); - Collection relationSpecifications; - if (relationSpecificationUris.isEmpty()) { - QName defaultRelation = ObjectUtils.defaultIfNull(prismContext.getDefaultRelation(), RelationTypes.MEMBER.getRelation()); - relationSpecifications = Collections.singleton(defaultRelation); - } else { - relationSpecifications = relationSpecificationUris.stream() - .map(uri -> QNameUtil.uriToQName(uri, true)) - .collect(Collectors.toSet()); - } - assert !relationSpecifications.isEmpty(); - - Collection resources; - try { - if (resourceParameterValue != null) { - PipelineData data = expressionHelper - .evaluateParameter(resourceParameterValue, null, input, context, globalResult); - resources = data.getDataAsReferences(ResourceType.COMPLEX_TYPE, ResourceType.class, context, globalResult); - } else { - resources = null; - } - } catch (CommonException e) { - throw new ScriptExecutionException("Couldn't evaluate '" + PARAM_RESOURCE + "' parameter of a scripting expression: " + e.getMessage(), e); - } + abstract P parseParameters(ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult result) throws SchemaException, ScriptExecutionException, ObjectNotFoundException, + SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException; - Collection roles; - try { - if (roleParameterValue != null) { - PipelineData data = expressionHelper.evaluateParameter(roleParameterValue, null, input, context, globalResult); - roles = data.getDataAsReferences(RoleType.COMPLEX_TYPE, AbstractRoleType.class, context, globalResult); // if somebody wants to assign Org, he has to use full reference value (including object type) - } else { - roles = null; - } - } catch (CommonException e) { - throw new ScriptExecutionException("Couldn't evaluate '" + PARAM_ROLE + "' parameter of a scripting expression: " + e.getMessage(), e); - } + private void apply(AssignmentHolderType object, P parameters, ExecutionContext context, OperationResult result) + throws SchemaException, ScriptExecutionException { + ObjectDelta delta = createDelta(object, parameters); + operationsHelper.applyDelta(delta, parameters.options, parameters.dryRun, context, result); + context.println("Modified " + object + optionsSuffix(parameters.options, parameters.dryRun)); + } - if (resources == null && roles == null) { - throw new ScriptExecutionException("Nothing to " + getName() + ": neither resource nor role specified"); - } + abstract ObjectDelta createDelta(AssignmentHolderType object, P parameters) throws SchemaException; - if (CollectionUtils.isEmpty(resources) && CollectionUtils.isEmpty(roles)) { - LOGGER.warn("No resources and no roles to unassign in a scripting expression"); - context.println("Warning: no resources and no roles to unassign"); // TODO some better handling? - return input; - } + @Override + protected Class getObjectType() { + return AssignmentHolderType.class; + } - for (PipelineItem item : input.getData()) { - PrismValue value = item.getValue(); - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); - context.checkTaskStop(); - if (value instanceof PrismObjectValue && ((PrismObjectValue) value).asObjectable() instanceof AssignmentHolderType) { - @SuppressWarnings({"unchecked", "raw"}) - PrismObject prismObject = ((PrismObjectValue) value).asPrismObject(); - AssignmentHolderType objectType = (AssignmentHolderType) prismObject.asObjectable(); - long started = operationsHelper.recordStart(context, objectType); - Throwable exception = null; - try { - operationsHelper.applyDelta(createDelta(objectType, resources, roles, relationSpecifications), executionOptions, dryRun, context, result); - operationsHelper.recordEnd(context, objectType, started, null); - } catch (Throwable ex) { - operationsHelper.recordEnd(context, objectType, started, ex); - exception = processActionException(ex, getName(), value, context); - } - context.println(createConsoleMessage(prismObject, executionOptions, dryRun, exception)); - } else { - //noinspection ThrowableNotThrown - processActionException(new ScriptExecutionException("Item is not a PrismObject of AssignmentHolderType"), getName(), value, context); - } - operationsHelper.trimAndCloneResult(result, globalResult, context); + @NotNull Collection getRolesParameter(ActionExpressionType action, PipelineData input, + ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException, SchemaException, + ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException, + ExpressionEvaluationException { + ActionParameterValueType roleParameterValue = expressionHelper.getArgument(action.getParameter(), PARAM_ROLE, + false, false, getActionName()); + if (roleParameterValue != null) { + PipelineData data = expressionHelper.evaluateParameter(roleParameterValue, null, input, context, globalResult); + // if somebody wants to assign Org, he has to use full reference value (including object type) + return data.getDataAsReferences(RoleType.COMPLEX_TYPE, AbstractRoleType.class, context, globalResult); + } else { + return Collections.emptyList(); } - return input; // TODO updated objects? } - @NotNull - private String createConsoleMessage(PrismObject object, ModelExecuteOptions executionOptions, - boolean dryRun, Throwable exception) { - return (exception != null ? "Attempted to modify " : "Modified ") + object - + optionsSuffix(executionOptions, dryRun) + exceptionSuffix(exception); + @NotNull Collection getResourcesParameter(ActionExpressionType action, PipelineData input, + ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException, SchemaException, + ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException, + ExpressionEvaluationException { + ActionParameterValueType resourceParameterValue = expressionHelper.getArgument(action.getParameter(), PARAM_RESOURCE, + false, false, getActionName()); + if (resourceParameterValue != null) { + PipelineData data = expressionHelper + .evaluateParameter(resourceParameterValue, null, input, context, globalResult); + return data.getDataAsReferences(ResourceType.COMPLEX_TYPE, ResourceType.class, context, globalResult); + } else { + return Collections.emptyList(); + } } - protected abstract ObjectDelta createDelta(AssignmentHolderType object, Collection resources, - Collection roles, Collection relationSpecifications) throws SchemaException; + @NotNull Collection getRelationsParameter(ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException, SchemaException, ConfigurationException, + ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException { + Collection relationSpecificationUris = expressionHelper.getArgumentValues(action.getParameter(), PARAM_RELATION, + false, false, getActionName(), input, context, String.class, globalResult); + return relationSpecificationUris.stream() + .map(uri -> QNameUtil.uriToQName(uri, true)) + .collect(Collectors.toSet()); + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/BaseActionExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/BaseActionExecutor.java index e863a09cf57..6d14aac3b83 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/BaseActionExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/BaseActionExecutor.java @@ -7,55 +7,42 @@ package com.evolveum.midpoint.model.impl.scripting.actions; -import com.evolveum.midpoint.model.api.ModelExecuteOptions; -import com.evolveum.midpoint.model.api.ModelService; -import com.evolveum.midpoint.model.api.TaskService; -import com.evolveum.midpoint.model.impl.scripting.ActionExecutor; -import com.evolveum.midpoint.model.impl.scripting.PipelineData; -import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; -import com.evolveum.midpoint.model.api.ScriptExecutionException; -import com.evolveum.midpoint.model.impl.scripting.ScriptingExpressionEvaluator; +import com.evolveum.midpoint.model.api.*; +import com.evolveum.midpoint.model.api.expr.MidpointFunctions; +import com.evolveum.midpoint.model.impl.scripting.*; import com.evolveum.midpoint.model.impl.scripting.helpers.ExpressionHelper; import com.evolveum.midpoint.model.impl.scripting.helpers.OperationsHelper; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; import com.evolveum.midpoint.provisioning.api.ProvisioningService; import com.evolveum.midpoint.repo.api.RepositoryService; +import com.evolveum.midpoint.schema.GetOperationOptionsBuilder; +import com.evolveum.midpoint.schema.RelationRegistry; +import com.evolveum.midpoint.schema.SchemaHelper; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.security.api.AuthorizationConstants; import com.evolveum.midpoint.security.api.SecurityContextManager; import com.evolveum.midpoint.security.enforcer.api.AuthorizationParameters; import com.evolveum.midpoint.security.enforcer.api.SecurityEnforcer; -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.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SecurityViolationException; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ModelExecuteOptionsType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.PartialProcessingOptionsType; -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; + +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; + +import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -import static com.evolveum.midpoint.xml.ns._public.common.common_3.PartialProcessingTypeType.SKIP; - /** - * @author mederly + * Superclass for all action executors. */ public abstract class BaseActionExecutor implements ActionExecutor { private static final Trace LOGGER = TraceManager.getTrace(BaseActionExecutor.class); - private static final String PARAM_RAW = "raw"; - private static final String PARAM_DRY_RUN = "dryRun"; - private static final String PARAM_SKIP_APPROVALS = "skipApprovals"; - private static final String PARAM_OPTIONS = "options"; - @Autowired protected ScriptingExpressionEvaluator scriptingExpressionEvaluator; @Autowired protected PrismContext prismContext; @Autowired protected OperationsHelper operationsHelper; @@ -66,46 +53,21 @@ public abstract class BaseActionExecutor implements ActionExecutor { @Autowired protected SecurityContextManager securityContextManager; @Autowired protected TaskService taskService; @Autowired @Qualifier("cacheRepositoryService") protected RepositoryService cacheRepositoryService; - - // todo move to some helper? - - protected ModelExecuteOptions getOptions(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult result) throws ScriptExecutionException { - boolean raw = expressionHelper.getArgumentAsBoolean(expression.getParameter(), PARAM_RAW, input, context, false, PARAM_RAW, result); - boolean skipApprovals = expressionHelper.getArgumentAsBoolean(expression.getParameter(), PARAM_SKIP_APPROVALS, input, context, false, PARAM_RAW, result); - ModelExecuteOptionsType optionsBean = expressionHelper.getSingleArgumentValue(expression.getParameter(), PARAM_OPTIONS, false, false, "options", input, context, - ModelExecuteOptionsType.class, result); - ModelExecuteOptions options; - if (optionsBean != null) { - options = ModelExecuteOptions.fromModelExecutionOptionsType(optionsBean); - } else { - options = new ModelExecuteOptions(); - } - if (raw) { - options.setRaw(true); - } - if (skipApprovals) { - if (options.getPartialProcessing() != null) { - options.getPartialProcessing().setApprovals(SKIP); - } else { - options.setPartialProcessing(new PartialProcessingOptionsType().approvals(SKIP)); - } - } - return options; - } - - protected boolean getParamDryRun(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult result) throws ScriptExecutionException { - return expressionHelper.getArgumentAsBoolean(expression.getParameter(), PARAM_DRY_RUN, input, context, false, PARAM_DRY_RUN, result); - } + @Autowired protected ScriptingActionExecutorRegistry actionExecutorRegistry; + @Autowired protected MidpointFunctions midpointFunctions; + @Autowired protected RelationRegistry relationRegistry; + @Autowired protected MatchingRuleRegistry matchingRuleRegistry; + @Autowired protected SchemaHelper schemaHelper; private String optionsSuffix(ModelExecuteOptions options) { return options.notEmpty() ? " " + options : ""; } - protected String drySuffix(boolean dry) { + String drySuffix(boolean dry) { return dry ? " (dry run)" : ""; } - protected String optionsSuffix(ModelExecuteOptions options, boolean dry) { + String optionsSuffix(ModelExecuteOptions options, boolean dry) { return optionsSuffix(options) + drySuffix(dry); } @@ -113,7 +75,7 @@ protected String exceptionSuffix(Throwable t) { return t != null ? " (error: " + t.getClass().getSimpleName() + ": " + t.getMessage() + ")" : ""; } - protected Throwable processActionException(Throwable e, String actionName, PrismValue value, ExecutionContext context) throws ScriptExecutionException { + Throwable processActionException(Throwable e, String actionName, PrismValue value, ExecutionContext context) throws ScriptExecutionException { if (context.isContinueOnAnyError()) { LoggingUtils.logUnexpectedException(LOGGER, "Couldn't execute action '{}' on {}: {}", e, actionName, value, e.getMessage()); @@ -123,8 +85,8 @@ protected Throwable processActionException(Throwable e, String actionName, Prism } } - protected void checkRootAuthorization(ExecutionContext context, - OperationResult globalResult, String actionName) throws ScriptExecutionException { + void checkRootAuthorization(ExecutionContext context, OperationResult globalResult, String actionName) + throws ScriptExecutionException { if (context.isPrivileged()) { return; } @@ -135,4 +97,58 @@ protected void checkRootAuthorization(ExecutionContext context, } } + @FunctionalInterface + public interface ItemProcessor { + void process(PrismValue value, PipelineItem item, OperationResult result) throws ScriptExecutionException, CommonException; + } + + @FunctionalInterface + public interface ConsoleFailureMessageWriter { + void write(PrismValue value, @NotNull Throwable exception); + } + + void iterateOverItems(PipelineData input, ExecutionContext context, OperationResult globalResult, + ItemProcessor itemProcessor, ConsoleFailureMessageWriter writer) + throws ScriptExecutionException { + + for (PipelineItem item : input.getData()) { + PrismValue value = item.getValue(); + OperationResult result = operationsHelper.createActionResult(item, this); + + context.checkTaskStop(); + long started; + if (value instanceof PrismObjectValue) { + started = operationsHelper.recordStart(context, asObjectType(value)); + } else { + started = 0; + } + try { + itemProcessor.process(value, item, result); + if (value instanceof PrismObjectValue) { + operationsHelper.recordEnd(context, asObjectType(value), started, null); + } + } catch (Throwable ex) { + if (value instanceof PrismObjectValue) { + operationsHelper.recordEnd(context, asObjectType(value), started, ex); + } + Throwable exception = processActionException(ex, getActionName(), value, context); + writer.write(value, exception); + } + operationsHelper.trimAndCloneResult(result, globalResult); + } + } + + private ObjectType asObjectType(PrismValue value) { + return (ObjectType) ((PrismObjectValue) value).asObjectable(); + } + + String getDescription(PrismValue value) { + if (value instanceof PrismObjectValue) { + return asObjectType(value).asPrismObject().toString(); + } else { + return value.toHumanReadableString(); + } + } + + abstract String getActionName(); } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/DeleteExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/DeleteExecutor.java index 5ca5d3fc03d..063e025e9ac 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/DeleteExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/DeleteExecutor.java @@ -11,77 +11,68 @@ import com.evolveum.midpoint.model.impl.scripting.PipelineData; import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; import com.evolveum.midpoint.model.api.ScriptExecutionException; -import com.evolveum.midpoint.model.api.PipelineItem; import com.evolveum.midpoint.model.impl.scripting.helpers.OperationsHelper; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectValue; -import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.DeleteActionExpressionType; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; /** - * @author mederly + * Executes the "delete" action. */ @Component -public class DeleteExecutor extends BaseActionExecutor { - - private static final Trace LOGGER = TraceManager.getTrace(DeleteExecutor.class); +public class DeleteExecutor extends AbstractObjectBasedActionExecutor { private static final String NAME = "delete"; - @Autowired - private OperationsHelper operationsHelper; - @PostConstruct public void init() { - scriptingExpressionEvaluator.registerActionExecutor(NAME, this); + actionExecutorRegistry.register(NAME, DeleteActionExpressionType.class, this); } @Override - public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { + public PipelineData execute(ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException, SchemaException, ObjectNotFoundException, + SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { - ModelExecuteOptions executionOptions = getOptions(expression, input, context, globalResult); - boolean dryRun = getParamDryRun(expression, input, context, globalResult); + boolean dryRun = operationsHelper.getDryRun(action, input, context, globalResult); + ModelExecuteOptions options = operationsHelper.getOptions(action, input, context, globalResult); + + iterateOverObjects(input, context, globalResult, + (object, item, result) -> + delete(object.asObjectable(), dryRun, options, context, result), + (object, exception) -> + context.println("Failed to delete " + object + drySuffix(dryRun) + exceptionSuffix(exception)) + ); - for (PipelineItem item : input.getData()) { - PrismValue value = item.getValue(); - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); - context.checkTaskStop(); - if (value instanceof PrismObjectValue) { - @SuppressWarnings({"unchecked", "raw"}) - PrismObject prismObject = ((PrismObjectValue) value).asPrismObject(); - ObjectType objectType = prismObject.asObjectable(); - long started = operationsHelper.recordStart(context, objectType); - Throwable exception = null; - try { - operationsHelper.applyDelta(createDeleteDelta(objectType), executionOptions, dryRun, context, result); - operationsHelper.recordEnd(context, objectType, started, null); - } catch (Throwable ex) { - operationsHelper.recordEnd(context, objectType, started, ex); - exception = processActionException(ex, NAME, value, context); - } - context.println((exception != null ? "Attempted to delete " : "Deleted ") + prismObject.toString() + optionsSuffix(executionOptions, dryRun) + exceptionSuffix(exception)); - } else { - //noinspection ThrowableNotThrown - processActionException(new ScriptExecutionException("Item is not a PrismObject"), NAME, value, context); - } - operationsHelper.trimAndCloneResult(result, globalResult, context); - } return input; } - private ObjectDelta createDeleteDelta(ObjectType objectType) { - return prismContext.deltaFactory().object().createDeleteDelta(objectType.getClass(), objectType.getOid() - ); + private void delete(ObjectType object, boolean dryRun, ModelExecuteOptions options, ExecutionContext context, + OperationResult result) throws ScriptExecutionException { + ObjectDelta deleteDelta = prismContext.deltaFactory().object() + .createDeleteDelta(object.getClass(), object.getOid()); + operationsHelper.applyDelta(deleteDelta, options, dryRun, context, result); + context.println("Deleted " + object + optionsSuffix(options, dryRun)); } + @Override + Class getObjectType() { + return ObjectType.class; + } + + @Override + String getActionName() { + return NAME; + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/DiscoverConnectorsExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/DiscoverConnectorsExecutor.java index 3715a81c3a6..63661356999 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/DiscoverConnectorsExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/DiscoverConnectorsExecutor.java @@ -15,10 +15,8 @@ import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.ReferenceDelta; import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.util.exception.CommunicationException; import com.evolveum.midpoint.util.exception.ConfigurationException; import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; @@ -29,7 +27,6 @@ import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ConnectorHostType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ConnectorType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; @@ -40,7 +37,10 @@ import java.util.*; /** - * @author mederly + * Executes "discover-connectors" action. + * + * There is no static (typed) definition of this action yet. + * Also, this code is not refactored yet. */ @Component public class DiscoverConnectorsExecutor extends BaseActionExecutor { @@ -52,11 +52,13 @@ public class DiscoverConnectorsExecutor extends BaseActionExecutor { @PostConstruct public void init() { - scriptingExpressionEvaluator.registerActionExecutor(NAME, this); + actionExecutorRegistry.register(NAME, this); } @Override - public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { + public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException, SchemaException, ConfigurationException, + ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException { boolean rebind = expressionHelper.getArgumentAsBoolean(expression.getParameter(), PARAM_REBIND_RESOURCES, input, context, false, PARAM_REBIND_RESOURCES, globalResult); @@ -64,7 +66,7 @@ public PipelineData execute(ActionExpressionType expression, PipelineData input, for (PipelineItem item: input.getData()) { PrismValue value = item.getValue(); - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); + OperationResult result = operationsHelper.createActionResult(item, this); context.checkTaskStop(); if (value instanceof PrismObjectValue && ((PrismObjectValue) value).asObjectable() instanceof ConnectorHostType) { PrismObject connectorHostTypePrismObject = ((PrismObjectValue) value).asPrismObject(); @@ -96,7 +98,7 @@ public PipelineData execute(ActionExpressionType expression, PipelineData input, //noinspection ThrowableNotThrown processActionException(new ScriptExecutionException("Input item is not a PrismObject"), NAME, value, context); } - operationsHelper.trimAndCloneResult(result, globalResult, context); + operationsHelper.trimAndCloneResult(result, globalResult); } return output; // TODO configurable output (either connector hosts or discovered connectors) } @@ -171,4 +173,9 @@ private void determineConnectorMappings(Map rebindMap, ConnectorT } } } + + @Override + String getActionName() { + return NAME; + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/EnableDisableExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/EnableDisableExecutor.java index 91f60b00ff3..d2b9e6e7eb2 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/EnableDisableExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/EnableDisableExecutor.java @@ -7,104 +7,92 @@ package com.evolveum.midpoint.model.impl.scripting.actions; +import static com.evolveum.midpoint.model.impl.scripting.helpers.ScriptingBeansUtil.getActionType; +import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS; + +import javax.annotation.PostConstruct; + +import com.evolveum.midpoint.model.impl.scripting.helpers.ScriptingBeansUtil; +import com.evolveum.midpoint.model.impl.scripting.helpers.ScriptingDataUtil; + +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.model.api.ModelExecuteOptions; -import com.evolveum.midpoint.model.impl.scripting.PipelineData; -import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; import com.evolveum.midpoint.model.api.ScriptExecutionException; -import com.evolveum.midpoint.model.api.PipelineItem; -import com.evolveum.midpoint.model.impl.scripting.helpers.OperationsHelper; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectValue; -import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; +import com.evolveum.midpoint.model.impl.scripting.PipelineData; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.DisableActionExpressionType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.EnableActionExpressionType; /** - * @author mederly + * Implements "enable" and "disable" actions. + * It is ObjectType-typed just because it handles both FocusType and ShadowType objects. */ @Component -public class EnableDisableExecutor extends BaseActionExecutor { - - private static final Trace LOGGER = TraceManager.getTrace(EnableDisableExecutor.class); +public class EnableDisableExecutor extends AbstractObjectBasedActionExecutor { private static final String NAME_ENABLE = "enable"; private static final String NAME_DISABLE = "disable"; - @Autowired - private OperationsHelper operationsHelper; - @PostConstruct public void init() { - scriptingExpressionEvaluator.registerActionExecutor(NAME_ENABLE, this); - scriptingExpressionEvaluator.registerActionExecutor(NAME_DISABLE, this); + actionExecutorRegistry.register(NAME_ENABLE, EnableActionExpressionType.class, this); + actionExecutorRegistry.register(NAME_DISABLE, DisableActionExpressionType.class, this); } @Override - public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { - - boolean isEnable = NAME_ENABLE.equals(expression.getType()); - ModelExecuteOptions executionOptions = getOptions(expression, input, context, globalResult); - boolean dryRun = getParamDryRun(expression, input, context, globalResult); - - for (PipelineItem item: input.getData()) { - PrismValue value = item.getValue(); - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); - result.addParam("operation", expression.getType()); - context.checkTaskStop(); - if (value instanceof PrismObjectValue) { - @SuppressWarnings({"unchecked", "raw"}) - PrismObject prismObject = ((PrismObjectValue) value).asPrismObject(); - ObjectType objectType = prismObject.asObjectable(); - long started = operationsHelper.recordStart(context, objectType); - Throwable exception = null; - try { - if (objectType instanceof FocusType) { - operationsHelper.applyDelta(createEnableDisableDelta((FocusType) objectType, isEnable), executionOptions, dryRun, context, result); - } else if (objectType instanceof ShadowType) { - operationsHelper.applyDelta(createEnableDisableDelta((ShadowType) objectType, isEnable), executionOptions, dryRun, context, result); - } else { - throw new ScriptExecutionException("Item is not a FocusType nor ShadowType: " + value.toString()); - } - operationsHelper.recordEnd(context, objectType, started, null); - } catch (Throwable ex) { - operationsHelper.recordEnd(context, objectType, started, ex); - exception = processActionException(ex, expression.getType(), value, context); - } - context.println((exception != null ? "Attempted to " + expression.getType() : (isEnable ? "Enabled " : "Disabled ")) - + prismObject.toString() + optionsSuffix(executionOptions, dryRun) + exceptionSuffix(exception)); - } else { - //noinspection ThrowableNotThrown - processActionException(new ScriptExecutionException("Item is not a PrismObject"), expression.getType(), value, context); - } - operationsHelper.trimAndCloneResult(result, globalResult, context); - } + public PipelineData execute(ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException, SchemaException, ObjectNotFoundException, + SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { + + ModelExecuteOptions options = operationsHelper.getOptions(action, input, context, globalResult); + boolean dryRun = operationsHelper.getDryRun(action, input, context, globalResult); + boolean isEnable = NAME_ENABLE.equals(getActionType(action)); + + iterateOverObjects(input, context, globalResult, + (object, item, result) -> + enableOrDisable(object.asObjectable(), dryRun, options, isEnable, context, result), + (object, exception) -> + context.println("Failed to " + (isEnable?"enable":"disable") + object + drySuffix(dryRun) + exceptionSuffix(exception)) + ); + return input; } - private ObjectDelta createEnableDisableDelta(FocusType focus, boolean isEnable) { - return prismContext.deltaFactory().object().createModificationReplaceProperty(focus.getClass(), - focus.getOid(), PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - isEnable ? ActivationStatusType.ENABLED : ActivationStatusType.DISABLED); + private void enableOrDisable(ObjectType object, boolean dryRun, ModelExecuteOptions options, boolean isEnable, + ExecutionContext context, OperationResult result) throws ScriptExecutionException, SchemaException { + if (object instanceof FocusType || object instanceof ShadowType) { + ObjectDelta delta = createEnableDisableDelta(object, isEnable); + operationsHelper.applyDelta(delta, options, dryRun, context, result); + context.println((isEnable ? "Enabled " : "Disabled ") + object + optionsSuffix(options, dryRun)); + } else { + throw new ScriptExecutionException("Object is not a FocusType nor ShadowType: " + object); + } } - private ObjectDelta createEnableDisableDelta(ShadowType shadow, boolean isEnable) { - return prismContext.deltaFactory().object().createModificationReplaceProperty(shadow.getClass(), - shadow.getOid(), PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - isEnable ? ActivationStatusType.ENABLED : ActivationStatusType.DISABLED); + private ObjectDelta createEnableDisableDelta(ObjectType object, boolean isEnable) + throws SchemaException { + return prismContext.deltaFor(object.getClass()) + .item(PATH_ACTIVATION_ADMINISTRATIVE_STATUS) + .replace(isEnable ? ActivationStatusType.ENABLED : ActivationStatusType.DISABLED) + .asObjectDelta(object.getOid()); } + @Override + Class getObjectType() { + return ObjectType.class; + } + + @Override + String getActionName() { + return "enable-disable"; + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ExecuteScriptExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ExecuteScriptExecutor.java new file mode 100644 index 00000000000..138e7ad9885 --- /dev/null +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ExecuteScriptExecutor.java @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.model.impl.scripting.actions; + +import com.evolveum.midpoint.model.api.PipelineItem; +import com.evolveum.midpoint.model.api.ScriptExecutionException; +import com.evolveum.midpoint.model.common.expression.script.ScriptExpression; +import com.evolveum.midpoint.model.common.expression.script.ScriptExpressionFactory; +import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; +import com.evolveum.midpoint.model.impl.scripting.PipelineData; +import com.evolveum.midpoint.model.impl.util.ModelImplUtils; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.xml.XmlTypeConverter; +import com.evolveum.midpoint.repo.common.expression.ExpressionFactory; +import com.evolveum.midpoint.repo.common.expression.ExpressionSyntaxException; +import com.evolveum.midpoint.repo.common.expression.ExpressionUtil; +import com.evolveum.midpoint.repo.common.expression.ExpressionVariables; +import com.evolveum.midpoint.schema.SchemaConstantsGenerated; +import com.evolveum.midpoint.schema.constants.ExpressionConstants; +import com.evolveum.midpoint.schema.expression.ExpressionProfile; +import com.evolveum.midpoint.schema.expression.TypedValue; +import com.evolveum.midpoint.schema.expression.VariablesMap; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.QNameUtil; +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.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.ScriptExpressionEvaluatorType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ExecuteScriptActionExpressionType; + +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.xml.namespace.QName; +import java.util.Collection; +import java.util.List; + +import static com.evolveum.midpoint.model.impl.scripting.VariablesUtil.cloneIfNecessary; + +/** + * Executes "execute-script" (s:execute) actions. + */ +@Component +public class ExecuteScriptExecutor extends BaseActionExecutor { + + @Autowired private ScriptExpressionFactory scriptExpressionFactory; + @Autowired private ExpressionFactory expressionFactory; + + private static final String NAME = "execute-script"; + private static final String PARAM_SCRIPT = "script"; + private static final String PARAM_QUIET = "quiet"; // could be useful for other actions as well + private static final String PARAM_OUTPUT_ITEM = "outputItem"; // item name or type (as URI!) -- EXPERIMENTAL + private static final String PARAM_FOR_WHOLE_INPUT = "forWholeInput"; + + @PostConstruct + public void init() { + actionExecutorRegistry.register(NAME, ExecuteScriptActionExpressionType.class, this); + } + + private static class Parameters { + @NotNull private final ScriptExpression scriptExpression; + private final ItemDefinition outputDefinition; + private final boolean forWholeInput; + private final boolean quiet; + + private Parameters(@NotNull ScriptExpression scriptExpression, + ItemDefinition outputDefinition, boolean forWholeInput, boolean quiet) { + this.scriptExpression = scriptExpression; + this.outputDefinition = outputDefinition; + this.forWholeInput = forWholeInput; + this.quiet = quiet; + } + } + + @Override + public PipelineData execute(ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException, SchemaException, ConfigurationException, + ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException { + + checkRootAuthorization(context, globalResult, NAME); + + Parameters parameters = getParameters(action, input, context, globalResult); + PipelineData output = PipelineData.createEmpty(); + + if (parameters.forWholeInput) { + executeForWholeInput(input, output, parameters, context, globalResult); + } else { + iterateOverItems(input, context, globalResult, + (value, item, result) -> + processItem(context, parameters, output, item, value, result), + (value, exception) -> + context.println("Failed to execute script on " + getDescription(value) + exceptionSuffix(exception))); + } + return output; + } + + private void executeForWholeInput(PipelineData input, PipelineData output, Parameters parameters, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException { + OperationResult result = operationsHelper.createActionResult(null, this); + context.checkTaskStop(); + try { + TypedValue inputTypedValue = new TypedValue<>(input, PipelineData.class); + Object outObject = executeScript(parameters.scriptExpression, inputTypedValue, context.getInitialVariables(), context, result); + if (outObject != null) { + addToData(outObject, PipelineData.newOperationResult(), output); + } else { + // no definition means we don't plan to provide any output - so let's just copy the input item to the output + // (actually, null definition with non-null outObject should not occur) + if (parameters.outputDefinition == null) { + output.addAllFrom(input); + } + } + if (!parameters.quiet) { + context.println("Executed script on the pipeline"); + } + + } catch (Throwable ex) { + Throwable exception = processActionException(ex, NAME, null, context); // TODO value for error reporting (3rd parameter) + context.println("Failed to execute script on the pipeline" + exceptionSuffix(exception)); + } + operationsHelper.trimAndCloneResult(result, globalResult); + } + + private void processItem(ExecutionContext context, Parameters parameters, + PipelineData output, PipelineItem item, PrismValue value, OperationResult result) + throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, CommunicationException, + ConfigurationException, SecurityViolationException { + // Hack. TODO: we need to add definitions to Pipeline items. + //noinspection unchecked + TypedValue typedValue = new TypedValue(value, value == null ? Object.class : value.getClass()); + Object outObject = executeScript(parameters.scriptExpression, typedValue, item.getVariables(), context, result); + if (outObject != null) { + addToData(outObject, item.getResult(), output); + } else { + // no definition means we don't plan to provide any output - so let's just copy the input item to the output + // (actually, null definition with non-null outObject should not occur) + if (parameters.outputDefinition == null) { + output.add(item); + } + } + if (!parameters.quiet) { + context.println("Executed script on " + getDescription(value)); + } + } + + private Parameters getParameters(ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws CommunicationException, ObjectNotFoundException, SchemaException, + ScriptExecutionException, SecurityViolationException, ConfigurationException, ExpressionEvaluationException { + ScriptExpressionEvaluatorType script = expressionHelper.getActionArgument(ScriptExpressionEvaluatorType.class, action, + ExecuteScriptActionExpressionType.F_SCRIPT, PARAM_SCRIPT, input, context, null, PARAM_SCRIPT, globalResult); + ItemDefinition outputDefinition; + String outputItemUri = expressionHelper.getSingleArgumentValue(action.getParameter(), PARAM_OUTPUT_ITEM, false, false, + NAME, input, context, String.class, globalResult); + if (StringUtils.isNotBlank(outputItemUri)) { + outputDefinition = getItemDefinition(outputItemUri); + } else if (action instanceof ExecuteScriptActionExpressionType) { + ExecuteScriptActionExpressionType execute = (ExecuteScriptActionExpressionType) action; + if (execute.getOutputItemName() != null) { + outputDefinition = getItemDefinitionFromItemName(execute.getOutputItemName()); + } else if (execute.getOutputTypeName() != null) { + outputDefinition = getItemDefinitionFromTypeName(execute.getOutputTypeName()); + } else { + outputDefinition = null; + } + } else { + outputDefinition = null; + } + boolean forWholeInput = expressionHelper.getActionArgument(Boolean.class, action, + ExecuteScriptActionExpressionType.F_FOR_WHOLE_INPUT, PARAM_FOR_WHOLE_INPUT, input, context, false, PARAM_FOR_WHOLE_INPUT, globalResult); + boolean quiet = expressionHelper.getActionArgument(Boolean.class, action, + ExecuteScriptActionExpressionType.F_QUIET, PARAM_QUIET, input, context, false, PARAM_QUIET, globalResult); + + if (script == null) { + throw new IllegalArgumentException("No script provided"); + } + + ExpressionProfile expressionProfile = null; // TODO + + ScriptExpression scriptExpression; + try { + scriptExpression = scriptExpressionFactory.createScriptExpression(script, outputDefinition, + expressionProfile, expressionFactory, "script", globalResult); + } catch (ExpressionSyntaxException | SecurityViolationException e) { + throw new ScriptExecutionException("Couldn't parse script expression: " + e.getMessage(), e); + } + + return new Parameters(scriptExpression, outputDefinition, forWholeInput, quiet); + } + + private void addToData(@NotNull Object outObject, @NotNull OperationResult result, PipelineData output) { + if (outObject instanceof Collection) { + for (Object o : (Collection) outObject) { + addToData(o, result, output); + } + } else { + PrismValue value; + if (outObject instanceof PrismValue) { + value = (PrismValue) outObject; + } else if (outObject instanceof Objectable) { + value = prismContext.itemFactory().createObjectValue((Objectable) outObject); + } else if (outObject instanceof Containerable) { + value = prismContext.itemFactory().createContainerValue((Containerable) outObject); + } else { + value = prismContext.itemFactory().createPropertyValue(outObject); + } + output.add(new PipelineItem(value, result)); + } + } + + private ItemDefinition getItemDefinition(String uri) throws ScriptExecutionException { + QName name = QNameUtil.uriToQName(uri, true); + ItemDefinition byName = prismContext.getSchemaRegistry().findItemDefinitionByElementName(name); + if (byName != null) { + return byName; + } + + ItemDefinition byType = prismContext.getSchemaRegistry().findItemDefinitionByType(name); + if (byType != null) { + return byType; + } + + throw new ScriptExecutionException("Supplied item identification '" + uri + "' corresponds neither to item name nor type name"); + } + + private ItemDefinition getItemDefinitionFromItemName(QName itemName) throws ScriptExecutionException { + ItemDefinition def = prismContext.getSchemaRegistry().findItemDefinitionByElementName(itemName); + if (def != null) { + return def; + } + throw new ScriptExecutionException("Item with name '" + itemName + "' couldn't be found."); + } + + private ItemDefinition getItemDefinitionFromTypeName(QName typeName) throws ScriptExecutionException { + ItemDefinition byType = prismContext.getSchemaRegistry().findItemDefinitionByType(typeName); + if (byType != null) { + return byType; + } + + if (XmlTypeConverter.canConvert(typeName)) { + return prismContext.definitionFactory().createPropertyDefinition(SchemaConstantsGenerated.C_VALUE, typeName); + } + + TypeDefinition typeDef = prismContext.getSchemaRegistry().findTypeDefinitionByType(typeName); + if (typeDef instanceof SimpleTypeDefinition) { + return prismContext.definitionFactory().createPropertyDefinition(SchemaConstantsGenerated.C_VALUE, typeName); + } else if (typeDef instanceof ComplexTypeDefinition) { + ComplexTypeDefinition ctd = (ComplexTypeDefinition) typeDef; + if (ctd.isContainerMarker() || ctd.isObjectMarker()) { + return prismContext.definitionFactory().createContainerDefinition(SchemaConstantsGenerated.C_VALUE, ctd); + } else { + return prismContext.definitionFactory().createPropertyDefinition(SchemaConstantsGenerated.C_VALUE, typeName); + } + } else if (typeDef != null) { + throw new ScriptExecutionException("Type with name '" + typeName + "' couldn't be used as output type: " + typeDef); + } else { + throw new ScriptExecutionException("Type with name '" + typeName + "' couldn't be found."); + } + } + + private Object executeScript(ScriptExpression scriptExpression, TypedValue inputTypedValue, + VariablesMap externalVariables, ExecutionContext context, OperationResult result) + throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException { + ExpressionVariables variables = new ExpressionVariables(); + variables.put(ExpressionConstants.VAR_INPUT, inputTypedValue); + variables.put(ExpressionConstants.VAR_PRISM_CONTEXT, prismContext, PrismContext.class); + ExpressionUtil.addActorVariable(variables, securityContextManager, prismContext); + //noinspection unchecked + externalVariables.forEach((k, v) -> variables.put(k, cloneIfNecessary(k, v))); + variables.registerAliasesFrom(externalVariables); + + List rv = ModelImplUtils.evaluateScript(scriptExpression, null, variables, true, "in '"+NAME+"' action", context.getTask(), result); + + if (rv == null || rv.size() == 0) { + return null; + } else if (rv.size() == 1) { + return rv.get(0); + } else { + return rv; // shouldn't occur; would cause problems + } + } + + @Override + String getActionName() { + return NAME; + } +} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/GenerateValueExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/GenerateValueExecutor.java index bda68090a8b..a1b8e5c8b48 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/GenerateValueExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/GenerateValueExecutor.java @@ -7,88 +7,81 @@ package com.evolveum.midpoint.model.impl.scripting.actions; +import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_CREDENTIALS_PASSWORD_VALUE; + +import javax.annotation.PostConstruct; + +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.GenerateValueActionExpressionType; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.model.api.ModelInteractionService; -import com.evolveum.midpoint.model.api.PipelineItem; import com.evolveum.midpoint.model.api.ScriptExecutionException; import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; import com.evolveum.midpoint.model.impl.scripting.PipelineData; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectValue; -import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.api_types_3.PolicyItemDefinitionType; import com.evolveum.midpoint.xml.ns._public.common.api_types_3.PolicyItemTargetType; import com.evolveum.midpoint.xml.ns._public.common.api_types_3.PolicyItemsDefinitionType; -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.UserType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; import com.evolveum.prism.xml.ns._public.types_3.ItemPathType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_CREDENTIALS_PASSWORD_VALUE; /** - * @author mederly + * Executes "generate-value" action. */ @Component -public class GenerateValueExecutor extends BaseActionExecutor { - - private static final Trace LOGGER = TraceManager.getTrace(GenerateValueExecutor.class); +public class GenerateValueExecutor extends AbstractObjectBasedActionExecutor { private static final String NAME = "generate-value"; - public static final String PARAMETER_ITEMS = "items"; + private static final String PARAMETER_ITEMS = "items"; @Autowired private ModelInteractionService modelInteraction; @PostConstruct public void init() { - scriptingExpressionEvaluator.registerActionExecutor(NAME, this); + actionExecutorRegistry.register(NAME, GenerateValueActionExpressionType.class, this); } @Override - public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { + public PipelineData execute(ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException, SchemaException, ConfigurationException, + ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException { - PolicyItemsDefinitionType itemsDefinition = expressionHelper.getSingleArgumentValue(expression.getParameter(), - PARAMETER_ITEMS, false, false, PARAMETER_ITEMS, input, context, - PolicyItemsDefinitionType.class, globalResult); - if (itemsDefinition == null) { + PolicyItemsDefinitionType itemsDefinition; + PolicyItemsDefinitionType configured = expressionHelper.getActionArgument(PolicyItemsDefinitionType.class, action, + GenerateValueActionExpressionType.F_ITEMS, PARAMETER_ITEMS, input, context, null, PARAMETER_ITEMS, globalResult); + if (configured != null) { + itemsDefinition = configured; + } else { itemsDefinition = new PolicyItemsDefinitionType().policyItemDefinition( new PolicyItemDefinitionType() .target(new PolicyItemTargetType().path(new ItemPathType(PATH_CREDENTIALS_PASSWORD_VALUE))) .execute(false)); } - for (PipelineItem item: input.getData()) { - PrismValue value = item.getValue(); - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); - context.checkTaskStop(); - if (value instanceof PrismObjectValue) { - PrismObject object = ((PrismObjectValue) value).asPrismObject(); - ObjectType objectBean = object.asObjectable(); - long started = operationsHelper.recordStart(context, objectBean); - Throwable exception = null; - try { - LOGGER.trace("Generating value(s) for {}", objectBean); + iterateOverObjects(input, context, globalResult, + (object, item, result) -> { modelInteraction.generateValue(object, itemsDefinition, context.getTask(), result); - operationsHelper.recordEnd(context, objectBean, started, null); - } catch (Throwable e) { - operationsHelper.recordEnd(context, objectBean, started, e); - exception = processActionException(e, NAME, value, context); - } - context.println((exception != null ? "Attempted to generate value(s) for " : "Generated value(s) for ") + objectBean.toString() + exceptionSuffix(exception)); - } else { - //noinspection ThrowableNotThrown - processActionException(new ScriptExecutionException("Item is not a PrismObject"), NAME, value, context); - } - operationsHelper.trimAndCloneResult(result, globalResult, context); - } + context.println("Generated value(s) for " + object); + }, + (object, exception) -> { + context.println("Failed to generate value(s) for " + object + exceptionSuffix(exception)); + }); return input; } + + @Override + String getActionName() { + return NAME; + } + + @Override + Class getObjectType() { + return ObjectType.class; + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/LogExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/LogExecutor.java index 5594c59bcc5..848d36d8365 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/LogExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/LogExecutor.java @@ -12,16 +12,19 @@ import com.evolveum.midpoint.model.api.ScriptExecutionException; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.util.DebugUtil; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.LogActionExpressionType; + import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; /** - * @author mederly + * Executes "log" scripting action. */ @Component public class LogExecutor extends BaseActionExecutor { @@ -29,39 +32,43 @@ public class LogExecutor extends BaseActionExecutor { private static final Trace LOGGER = TraceManager.getTrace(LogExecutor.class); public static final String NAME = "log"; - public static final String PARAM_LEVEL = "level"; - public static final String PARAM_MESSAGE = "message"; - public static final String LEVEL_INFO = "info"; - public static final String LEVEL_DEBUG = "debug"; - public static final String LEVEL_TRACE = "trace"; + private static final String PARAM_LEVEL = "level"; + private static final String PARAM_MESSAGE = "message"; + private static final String LEVEL_INFO = "info"; + private static final String LEVEL_DEBUG = "debug"; + private static final String LEVEL_TRACE = "trace"; + + private static final String DEFAULT_MESSAGE = "Current data: "; + private static final String DEFAULT_LEVEL = LEVEL_INFO; @PostConstruct public void init() { - scriptingExpressionEvaluator.registerActionExecutor(NAME, this); + actionExecutorRegistry.register(NAME, LogActionExpressionType.class,this); } @Override - public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult parentResult) throws ScriptExecutionException { + public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException, SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { - String levelAsString = expressionHelper.getArgumentAsString(expression.getParameter(), PARAM_LEVEL, input, context, LEVEL_INFO, NAME, parentResult); - String message = expressionHelper.getArgumentAsString(expression.getParameter(), PARAM_MESSAGE, input, context, "Current data: ", NAME, parentResult); - message += "{}"; + String message = expressionHelper.getActionArgument(String.class, expression, + LogActionExpressionType.F_MESSAGE, PARAM_MESSAGE, input, context, DEFAULT_MESSAGE, NAME, globalResult) + "{}"; + String level = expressionHelper.getActionArgument(String.class, expression, + LogActionExpressionType.F_LEVEL, PARAM_LEVEL, input, context, DEFAULT_LEVEL, NAME, globalResult); - if (LEVEL_INFO.equals(levelAsString)) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info(message, DebugUtil.debugDump(input)); - } - } else if (LEVEL_DEBUG.equals(levelAsString)) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug(message, DebugUtil.debugDump(input)); - } - } else if (LEVEL_TRACE.equals(levelAsString)) { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace(message, DebugUtil.debugDump(input)); - } + if (LEVEL_INFO.equalsIgnoreCase(level)) { + LOGGER.info(message, DebugUtil.debugDumpLazily(input)); + } else if (LEVEL_DEBUG.equalsIgnoreCase(level)) { + LOGGER.debug(message, DebugUtil.debugDumpLazily(input)); + } else if (LEVEL_TRACE.equalsIgnoreCase(level)) { + LOGGER.trace(message, DebugUtil.debugDumpLazily(input)); } else { - LOGGER.warn("Invalid logging level specified for 'log' scripting action: " + levelAsString); + LOGGER.warn("Invalid logging level specified for 'log' scripting action: " + level); } return input; } + + @Override + String getActionName() { + return NAME; + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ModifyExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ModifyExecutor.java index 7122aa7b076..2f21b0104d2 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ModifyExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ModifyExecutor.java @@ -7,115 +7,110 @@ package com.evolveum.midpoint.model.impl.scripting.actions; +import javax.annotation.PostConstruct; + +import com.evolveum.midpoint.util.exception.*; + +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.model.api.ModelExecuteOptions; +import com.evolveum.midpoint.model.api.ScriptExecutionException; +import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; import com.evolveum.midpoint.model.impl.scripting.PipelineData; import com.evolveum.midpoint.model.impl.util.ModelImplUtils; -import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; -import com.evolveum.midpoint.model.api.ScriptExecutionException; -import com.evolveum.midpoint.model.api.PipelineItem; -import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.schema.DeltaConvertor; import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionParameterValueType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ModifyActionExpressionType; import com.evolveum.prism.xml.ns._public.types_3.ChangeTypeType; import com.evolveum.prism.xml.ns._public.types_3.EvaluationTimeType; import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - /** - * @author mederly + * Executor for 'modify' actions. */ @Component -public class ModifyExecutor extends BaseActionExecutor { - - private static final Trace LOGGER = TraceManager.getTrace(ModifyExecutor.class); +public class ModifyExecutor extends AbstractObjectBasedActionExecutor { private static final String NAME = "modify"; private static final String PARAM_DELTA = "delta"; @PostConstruct public void init() { - scriptingExpressionEvaluator.registerActionExecutor(NAME, this); + actionExecutorRegistry.register(NAME, ModifyActionExpressionType.class, this); } @Override - public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { - - ModelExecuteOptions executionOptions = getOptions(expression, input, context, globalResult); - boolean dryRun = getParamDryRun(expression, input, context, globalResult); - - ActionParameterValueType deltaParameterValue = expressionHelper.getArgument(expression.getParameter(), PARAM_DELTA, true, true, NAME); - PipelineData deltaData = expressionHelper.evaluateParameter(deltaParameterValue, ObjectDeltaType.class, input, context, globalResult); - - for (PipelineItem item: input.getData()) { - PrismValue value = item.getValue(); - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); - context.checkTaskStop(); - if (value instanceof PrismObjectValue) { - @SuppressWarnings({"unchecked", "raw"}) - PrismObject prismObject = ((PrismObjectValue) value).asPrismObject(); - ObjectType objectType = prismObject.asObjectable(); - long started = operationsHelper.recordStart(context, objectType); - Throwable exception = null; - try { - ObjectDelta delta = createDelta(objectType, deltaData); - result.addParam("delta", delta); - // This is only a preliminary solution for MID-4138. There are few things to improve: - // 1. References could be resolved earlier (before the main cycle); however it would require much more - // coding, as we have only skeleton of ObjectDeltaType there - we don't know the specific object type - // the delta will be applied to. It is not a big problem, but still a bit of work. - // 2. If the evaluation time is IMPORT, and the bulk action is part of a task that is being imported into - // repository, it should be perhaps resolved at that time. But again, it is a lot of work and it does - // not cover bulk actions which are not part of a task. - // We consider this solution to be adequate for now. - ModelImplUtils.resolveReferences(delta, cacheRepositoryService, false, false, EvaluationTimeType.IMPORT, true, prismContext, result); - operationsHelper.applyDelta(delta, executionOptions, dryRun, context, result); - operationsHelper.recordEnd(context, objectType, started, null); - } catch (Throwable ex) { - operationsHelper.recordEnd(context, objectType, started, ex); - exception = processActionException(ex, NAME, value, context); - } - context.println((exception != null ? "Attempted to modify " : "Modified ") + prismObject.toString() + optionsSuffix(executionOptions, dryRun) + exceptionSuffix(exception)); - } else { - //noinspection ThrowableNotThrown - processActionException(new ScriptExecutionException("Item is not a PrismObject"), NAME, value, context); - } - operationsHelper.trimAndCloneResult(result, globalResult, context); + public PipelineData execute(ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException, SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { + + ModelExecuteOptions options = operationsHelper.getOptions(action, input, context, globalResult); + boolean dryRun = operationsHelper.getDryRun(action, input, context, globalResult); + ObjectDeltaType deltaBean = expressionHelper.getActionArgument(ObjectDeltaType.class, action, + ModifyActionExpressionType.F_DELTA, PARAM_DELTA, input, context, null, + PARAM_DELTA, globalResult); + if (deltaBean == null) { + throw new SchemaException("Found no delta to be applied"); } + + iterateOverObjects(input, context, globalResult, + (object, item, result) -> + modify(object, dryRun, options, deltaBean, context, result), + (object, exception) -> + context.println("Failed to recompute " + object + drySuffix(dryRun) + exceptionSuffix(exception)) + ); + return input; } - private ObjectDelta createDelta(ObjectType objectType, PipelineData deltaData) throws ScriptExecutionException { - if (deltaData.getData().size() != 1) { - throw new ScriptExecutionException("Expected exactly one delta to apply, found " + deltaData.getData().size() + " instead."); - } - @SuppressWarnings({"unchecked", "raw"}) - ObjectDeltaType deltaType = ((PrismPropertyValue) deltaData.getData().get(0).getValue()).clone().getRealValue(); - if (deltaType.getChangeType() == null) { - deltaType.setChangeType(ChangeTypeType.MODIFY); + private void modify(PrismObject object, boolean dryRun, ModelExecuteOptions options, + ObjectDeltaType deltaBean, ExecutionContext context, OperationResult result) + throws ScriptExecutionException, SchemaException { + ObjectDelta delta = createDelta(object.asObjectable(), deltaBean); + result.addParam("delta", delta); + + // This is only a preliminary solution for MID-4138. There are few things to improve: + // 1. References could be resolved earlier (before the main cycle); however it would require much more + // coding, as we have only skeleton of ObjectDeltaType there - we don't know the specific object type + // the delta will be applied to. It is not a big problem, but still a bit of work. + // 2. If the evaluation time is IMPORT, and the bulk action is part of a task that is being imported into + // repository, it should be perhaps resolved at that time. But again, it is a lot of work and it does + // not cover bulk actions which are not part of a task. + // We consider this solution to be adequate for now. + ModelImplUtils.resolveReferences(delta, cacheRepositoryService, false, false, + EvaluationTimeType.IMPORT, true, prismContext, result); + + operationsHelper.applyDelta(delta, options, dryRun, context, result); + context.println("Modified " + object + optionsSuffix(options, dryRun)); + } + + private ObjectDelta createDelta(ObjectType object, ObjectDeltaType deltaBean) + throws ScriptExecutionException, SchemaException { + if (deltaBean.getChangeType() == null) { + deltaBean.setChangeType(ChangeTypeType.MODIFY); } - if (deltaType.getOid() == null && deltaType.getChangeType() != ChangeTypeType.ADD) { - deltaType.setOid(objectType.getOid()); + if (deltaBean.getOid() == null && deltaBean.getChangeType() != ChangeTypeType.ADD) { + deltaBean.setOid(object.getOid()); } - if (deltaType.getObjectType() == null) { - if (objectType.asPrismObject().getDefinition() == null) { - throw new ScriptExecutionException("No definition for prism object " + objectType); + if (deltaBean.getObjectType() == null) { + if (object.asPrismObject().getDefinition() == null) { + throw new ScriptExecutionException("No definition for prism object " + object); } - deltaType.setObjectType(objectType.asPrismObject().getDefinition().getTypeName()); - } - try { - return DeltaConvertor.createObjectDelta(deltaType, prismContext); - } catch (SchemaException e) { - throw new ScriptExecutionException("Couldn't process delta due to schema exception", e); + deltaBean.setObjectType(object.asPrismObject().getDefinition().getTypeName()); } + return DeltaConvertor.createObjectDelta(deltaBean, prismContext); + } + + @Override + Class getObjectType() { + return ObjectType.class; + } + + @Override + String getActionName() { + return NAME; } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/NotifyExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/NotifyExecutor.java index 56973eb8fe0..67a5768c6b9 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/NotifyExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/NotifyExecutor.java @@ -7,32 +7,35 @@ package com.evolveum.midpoint.model.impl.scripting.actions; +import static java.util.Objects.requireNonNull; + +import java.util.concurrent.atomic.AtomicInteger; +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.model.api.ScriptExecutionException; -import com.evolveum.midpoint.model.impl.scripting.PipelineData; import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; -import com.evolveum.midpoint.model.api.PipelineItem; +import com.evolveum.midpoint.model.impl.scripting.PipelineData; import com.evolveum.midpoint.notifications.api.NotificationManager; import com.evolveum.midpoint.notifications.api.events.CustomEvent; import com.evolveum.midpoint.notifications.api.events.factory.CustomEventFactory; -import com.evolveum.midpoint.prism.PrismValue; import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.xml.ns._public.common.common_3.EventHandlerType; import com.evolveum.midpoint.xml.ns._public.common.common_3.EventOperationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.EventStatusType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.NotifyActionExpressionType; /** - * @author mederly + * Executes "notify" actions. */ @Component public class NotifyExecutor extends BaseActionExecutor { - @Autowired(required = false) // During some tests this might be unavailable + @Autowired(required = false) // During some tests this might be unavailable private NotificationManager notificationManager; @Autowired(required = false) @@ -47,56 +50,54 @@ public class NotifyExecutor extends BaseActionExecutor { @PostConstruct public void init() { - scriptingExpressionEvaluator.registerActionExecutor(NAME, this); + actionExecutorRegistry.register(NAME, NotifyActionExpressionType.class, this); } @Override - public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { + public PipelineData execute(ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException, SchemaException, ObjectNotFoundException, + SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { - String subtype = expressionHelper.getArgumentAsString(expression.getParameter(), PARAM_SUBTYPE, input, context, null, PARAM_SUBTYPE, globalResult); - EventHandlerType handler = expressionHelper.getSingleArgumentValue(expression.getParameter(), PARAM_HANDLER, false, false, - PARAM_HANDLER, input, context, EventHandlerType.class, globalResult); - EventStatusType status = expressionHelper.getSingleArgumentValue(expression.getParameter(), PARAM_STATUS, false, false, - PARAM_STATUS, input, context, EventStatusType.class, globalResult); - EventOperationType operation = expressionHelper.getSingleArgumentValue(expression.getParameter(), PARAM_OPERATION, false, false, - PARAM_OPERATION, input, context, EventOperationType.class, globalResult); - boolean forWholeInput = expressionHelper.getArgumentAsBoolean(expression.getParameter(), PARAM_FOR_WHOLE_INPUT, input, context, false, PARAM_FOR_WHOLE_INPUT, globalResult); + String subtype = expressionHelper.getActionArgument(String.class, action, + NotifyActionExpressionType.F_SUBTYPE, PARAM_SUBTYPE, input, context, null, PARAM_SUBTYPE, globalResult); + EventHandlerType handler = expressionHelper.getActionArgument(EventHandlerType.class, action, + NotifyActionExpressionType.F_HANDLER, PARAM_HANDLER, input, context, null, PARAM_HANDLER, globalResult); + EventStatusType status = expressionHelper.getActionArgument(EventStatusType.class, action, + NotifyActionExpressionType.F_STATUS, PARAM_STATUS, input, context, EventStatusType.SUCCESS, PARAM_STATUS, globalResult); + EventOperationType operation = expressionHelper.getActionArgument(EventOperationType.class, action, + NotifyActionExpressionType.F_OPERATION, PARAM_OPERATION, input, context, EventOperationType.ADD, PARAM_OPERATION, globalResult); + boolean forWholeInput = expressionHelper.getActionArgument(Boolean.class, action, + NotifyActionExpressionType.F_FOR_WHOLE_INPUT, PARAM_FOR_WHOLE_INPUT, input, context, false, PARAM_FOR_WHOLE_INPUT, globalResult); if (handler != null) { - checkRootAuthorization(context, globalResult, NAME); // TODO explain that the reason is that handler is not null - } - - if (status == null) { - status = EventStatusType.SUCCESS; - } - if (operation == null) { - operation = EventOperationType.ADD; + checkRootAuthorization(context, globalResult, NAME); // TODO explain that the reason is that handler is not null } - if (notificationManager == null) { - throw new IllegalStateException("Notification manager is unavailable"); - } - if (customEventFactory == null) { - throw new IllegalStateException("Custom event factory is unavailable"); - } + requireNonNull(notificationManager, "Notification manager is unavailable"); + requireNonNull(customEventFactory, "Custom event factory is unavailable"); - int eventCount = 0; + AtomicInteger eventCount = new AtomicInteger(); if (forWholeInput) { CustomEvent event = customEventFactory.createEvent(subtype, handler, input.getData(), operation, status, context.getChannel()); notificationManager.processEvent(event, context.getTask(), globalResult); - eventCount++; + eventCount.incrementAndGet(); } else { - for (PipelineItem item: input.getData()) { - PrismValue value = item.getValue(); - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); - context.checkTaskStop(); - CustomEvent event = customEventFactory.createEvent(subtype, handler, value, operation, status, context.getChannel()); - notificationManager.processEvent(event, context.getTask(), result); - eventCount++; - operationsHelper.trimAndCloneResult(result, globalResult, context); - } + iterateOverItems(input, context, globalResult, + (value, item, result) -> { + CustomEvent event = customEventFactory.createEvent(subtype, handler, value, operation, status, context.getChannel()); + notificationManager.processEvent(event, context.getTask(), result); + eventCount.incrementAndGet(); + }, + (value, exception) -> { + context.println("Failed to notify on " + getDescription(value) + exceptionSuffix(exception)); + }); } - context.println("Produced " + eventCount + " event(s)"); + context.println("Produced " + eventCount.get() + " event(s)"); return input; } + + @Override + String getActionName() { + return NAME; + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/PurgeSchemaExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/PurgeSchemaExecutor.java index 986bfba45de..ed042b0f2d3 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/PurgeSchemaExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/PurgeSchemaExecutor.java @@ -7,86 +7,74 @@ package com.evolveum.midpoint.model.impl.scripting.actions; -import com.evolveum.midpoint.model.api.ModelExecuteOptions; -import com.evolveum.midpoint.model.impl.scripting.PipelineData; -import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; -import com.evolveum.midpoint.model.api.ScriptExecutionException; +import javax.annotation.PostConstruct; + +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.model.api.PipelineItem; -import com.evolveum.midpoint.prism.*; -import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.model.api.ScriptExecutionException; +import com.evolveum.midpoint.model.api.util.ResourceUtils; +import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; +import com.evolveum.midpoint.model.impl.scripting.PipelineData; +import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.XmlSchemaType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; - -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.PurgeSchemaActionExpressionType; /** - * @author mederly + * Executes "purge-schema" action. */ @Component -public class PurgeSchemaExecutor extends BaseActionExecutor { - - private static final Trace LOGGER = TraceManager.getTrace(PurgeSchemaExecutor.class); +public class PurgeSchemaExecutor extends AbstractObjectBasedActionExecutor { private static final String NAME = "purge-schema"; @PostConstruct public void init() { - scriptingExpressionEvaluator.registerActionExecutor(NAME, this); + actionExecutorRegistry.register(NAME, PurgeSchemaActionExpressionType.class, this); } @Override - public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { + public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException { PipelineData output = PipelineData.createEmpty(); - for (PipelineItem item: input.getData()) { - PrismValue value = item.getValue(); - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); - context.checkTaskStop(); - if (value instanceof PrismObjectValue && ((PrismObjectValue) value).asObjectable() instanceof ResourceType) { - PrismObject resourceTypePrismObject = ((PrismObjectValue) value).asPrismObject(); - ResourceType resourceType = resourceTypePrismObject.asObjectable(); - long started = operationsHelper.recordStart(context, resourceType); - ObjectDelta delta = createDelta(resourceTypePrismObject.asObjectable()); - try { - if (delta != null) { - operationsHelper.applyDelta(delta, ModelExecuteOptions.createRaw(), context, result); - context.println("Purged schema information from " + resourceTypePrismObject); - output.addValue(operationsHelper.getObject(ResourceType.class, resourceTypePrismObject.getOid(), true, context, result).getValue(), item.getResult(), item.getVariables()); - } else { - context.println("There's no schema information to be purged in " + value); - output.addValue(resourceTypePrismObject.getValue(), item.getResult(), item.getVariables()); - } - operationsHelper.recordEnd(context, resourceType, started, null); - } catch (Throwable ex) { - operationsHelper.recordEnd(context, resourceType, started, ex); - Throwable exception = processActionException(ex, NAME, value, context); - context.println("Couldn't purge schema information from " + resourceTypePrismObject + exceptionSuffix(exception)); - } - } else { - //noinspection ThrowableNotThrown - processActionException(new ScriptExecutionException("Item is not a PrismObject"), NAME, value, context); - } - operationsHelper.trimAndCloneResult(result, globalResult, context); - } + iterateOverObjects(input, context, globalResult, + (object, item, result) -> + purge(object, item, output, context, result), + (object, exception) -> + context.println("Failed to purge schema in " + object + exceptionSuffix(exception)) + ); + return output; } - private ObjectDelta createDelta(ResourceType resourceType) throws ScriptExecutionException { - PrismContainer schemaContainer = resourceType.asPrismObject().findContainer(ResourceType.F_SCHEMA); - if (schemaContainer == null || schemaContainer.isEmpty()) { - return null; - } - return prismContext.deltaFactory().object().createModificationDeleteContainer( - ResourceType.class, - resourceType.getOid(), - ResourceType.F_SCHEMA, - schemaContainer.getValue().clone()); + private void purge(PrismObject resource, PipelineItem item, PipelineData output, + ExecutionContext context, OperationResult result) throws ScriptExecutionException, + ExpressionEvaluationException, SchemaException, CommunicationException, ObjectAlreadyExistsException, + PolicyViolationException, SecurityViolationException, ConfigurationException, ObjectNotFoundException { + + ResourceUtils.deleteSchema(resource, modelService, prismContext, context.getTask(), result); + context.println("Purged schema information from " + resource); + + // It is questionable if noFetch should be used here. But it was so for a number of years. + // (Actually, the resource was fetched because of model operation used to implement + // deleteSchema method. So there is a complete version in the repository anyway.) + PrismObject resourceAfter = operationsHelper.getObject(ResourceType.class, + resource.getOid(), true, context, result); + output.addValue(resourceAfter.getValue(), item.getResult(), item.getVariables()); + } + + @Override + Class getObjectType() { + return ResourceType.class; + } + + @Override + String getActionName() { + return NAME; } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/RecomputeExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/RecomputeExecutor.java index fb74e93981b..9cc1018dd64 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/RecomputeExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/RecomputeExecutor.java @@ -8,84 +8,95 @@ package com.evolveum.midpoint.model.impl.scripting.actions; import com.evolveum.midpoint.model.api.ModelExecuteOptions; -import com.evolveum.midpoint.model.impl.lens.Clockwork; -import com.evolveum.midpoint.model.impl.lens.ContextFactory; import com.evolveum.midpoint.model.impl.scripting.PipelineData; import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; import com.evolveum.midpoint.model.api.ScriptExecutionException; -import com.evolveum.midpoint.model.api.PipelineItem; import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectValue; -import com.evolveum.midpoint.prism.PrismValue; -import com.evolveum.midpoint.prism.delta.ChangeType; import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.xml.XmlTypeConverter; import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; +import com.evolveum.midpoint.util.exception.*; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentHolderType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TriggerCreationType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; -import org.springframework.beans.factory.annotation.Autowired; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.RecomputeActionExpressionType; + import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; /** - * @author mederly + * Executes "recompute" action. */ @Component -public class RecomputeExecutor extends BaseActionExecutor { - - private static final Trace LOGGER = TraceManager.getTrace(RecomputeExecutor.class); +public class RecomputeExecutor extends AbstractObjectBasedActionExecutor { private static final String NAME = "recompute"; - @Autowired - private ContextFactory contextFactory; - - @Autowired - private Clockwork clockwork; - @PostConstruct public void init() { - scriptingExpressionEvaluator.registerActionExecutor(NAME, this); + actionExecutorRegistry.register(NAME, RecomputeActionExpressionType.class, this); } @Override - public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { - - boolean dryRun = getParamDryRun(expression, input, context, globalResult); - - for (PipelineItem item: input.getData()) { - PrismValue value = item.getValue(); - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); - context.checkTaskStop(); - if (value instanceof PrismObjectValue && FocusType.class.isAssignableFrom(((PrismObjectValue) value).asPrismObject().getCompileTimeClass())) { - PrismObject focalPrismObject = ((PrismObjectValue) value).asPrismObject(); - FocusType focusType = focalPrismObject.asObjectable(); - long started = operationsHelper.recordStart(context, focusType); - Throwable exception = null; - try { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Recomputing object {} with dryRun={}", focalPrismObject, dryRun); - } - ObjectDelta emptyDelta = prismContext.deltaFactory().object() - .createEmptyDelta(focusType.getClass(), focusType.getOid(), ChangeType.MODIFY - ); - operationsHelper.applyDelta(emptyDelta, ModelExecuteOptions.createReconcile(), dryRun, context, result); - LOGGER.trace("Recomputing of object {}: {}", focalPrismObject, result.getStatus()); - operationsHelper.recordEnd(context, focusType, started, null); - } catch (Throwable e) { - operationsHelper.recordEnd(context, focusType, started, e); - exception = processActionException(e, NAME, value, context); - } - context.println((exception != null ? "Attempted to recompute " : "Recomputed ") + focalPrismObject.toString() + drySuffix(dryRun) + exceptionSuffix(exception)); + public PipelineData execute(ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException, SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { + + boolean dryRun = operationsHelper.getDryRun(action, input, context, globalResult); + ModelExecuteOptions options = operationsHelper.getOptions(action, input, context, globalResult); + options.setReconcile(true); + TriggerCreationType triggerCreation = action instanceof RecomputeActionExpressionType ? + ((RecomputeActionExpressionType) action).getTriggered() : null; + + iterateOverObjects(input, context, globalResult, + (object, item, result) -> + recompute(object, dryRun, options, triggerCreation, context, result), + (object, exception) -> + context.println("Failed to recompute " + object + drySuffix(dryRun) + exceptionSuffix(exception)) + ); + + return input; + } + + private void recompute(PrismObject object, boolean dryRun, ModelExecuteOptions options, + TriggerCreationType triggerCreation, ExecutionContext context, OperationResult result) + throws ScriptExecutionException, SchemaException, ObjectAlreadyExistsException, ObjectNotFoundException { + + AssignmentHolderType objectable = object.asObjectable(); + if (triggerCreation == null) { + ObjectDelta emptyDelta = prismContext.deltaFactory().object() + .createEmptyModifyDelta(objectable.getClass(), objectable.getOid()); + operationsHelper.applyDelta(emptyDelta, options, dryRun, context, result); + context.println("Recomputed " + object.toString() + drySuffix(dryRun)); + } else if (dryRun) { + context.println("Skipping dry run of triggered-recompute of " + object.toString()); + } else if (triggerCreation.getFireAfter() == null) { + // direct trigger creation + midpointFunctions.createRecomputeTrigger(objectable.getClass(), objectable.getOid()); + context.println("Triggered recompute of " + object.toString()); + } else { + // optimized trigger creation + long fireAfter = XmlTypeConverter.toMillis(triggerCreation.getFireAfter()); + long safetyMargin = triggerCreation.getSafetyMargin() != null ? + XmlTypeConverter.toMillis(triggerCreation.getSafetyMargin()) : 0; + boolean triggerCreated = midpointFunctions.getOptimizingTriggerCreator(fireAfter, safetyMargin) + .createForObject(objectable.getClass(), objectable.getOid()); + if (triggerCreated) { + context.println("Triggered recompute of " + object.toString()); } else { - //noinspection ThrowableNotThrown - processActionException(new ScriptExecutionException("Item is not a PrismObject"), NAME, value, context); + context.println("Skipped triggering recompute of " + object.toString() + " because a trigger was already present"); } - operationsHelper.trimAndCloneResult(result, globalResult, context); } - return input; + } + + @Override + Class getObjectType() { + return AssignmentHolderType.class; + } + + @Override + protected String getActionName() { + return NAME; } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ReencryptExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ReencryptExecutor.java index a2e346c7c16..3b645c7ecd4 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ReencryptExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ReencryptExecutor.java @@ -16,6 +16,7 @@ import com.evolveum.midpoint.prism.crypto.Protector; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; import org.springframework.stereotype.Component; @@ -24,7 +25,10 @@ import java.util.Collection; /** - * @author mederly + * Executes "reencrypt" action. + * + * There is no static (typed) definition of this action yet. + * Also, this code is not refactored yet. */ @Component public class ReencryptExecutor extends BaseActionExecutor { @@ -35,21 +39,21 @@ public class ReencryptExecutor extends BaseActionExecutor { @PostConstruct public void init() { - scriptingExpressionEvaluator.registerActionExecutor(NAME, this); + actionExecutorRegistry.register(NAME, this); } @Override - public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { + public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException, SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException { Protector protector = prismContext.getDefaultProtector(); - boolean dryRun = getParamDryRun(expression, input, context, globalResult); + boolean dryRun = operationsHelper.getDryRun(expression, input, context, globalResult); PipelineData output = PipelineData.createEmpty(); for (PipelineItem item: input.getData()) { PrismValue value = item.getValue(); - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); + OperationResult result = operationsHelper.createActionResult(item, this); context.checkTaskStop(); if (value instanceof PrismObjectValue) { @SuppressWarnings({"unchecked", "raw"}) @@ -81,8 +85,13 @@ public PipelineData execute(ActionExpressionType expression, PipelineData input, //noinspection ThrowableNotThrown processActionException(new ScriptExecutionException("Item is not a PrismObject"), NAME, value, context); } - operationsHelper.trimAndCloneResult(result, globalResult, context); + operationsHelper.trimAndCloneResult(result, globalResult); } return output; } + + @Override + String getActionName() { + return NAME; + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ResolveExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ResolveExecutor.java index 682df7c0e3d..ca69b92e911 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ResolveExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ResolveExecutor.java @@ -7,76 +7,98 @@ package com.evolveum.midpoint.model.impl.scripting.actions; -import com.evolveum.midpoint.model.impl.scripting.PipelineData; -import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; -import com.evolveum.midpoint.model.api.ScriptExecutionException; +import java.util.Collection; +import javax.annotation.PostConstruct; +import javax.xml.namespace.QName; + +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.model.api.PipelineItem; -import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.model.api.ScriptExecutionException; +import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; +import com.evolveum.midpoint.model.impl.scripting.PipelineData; +import com.evolveum.midpoint.prism.PrismObjectValue; +import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.schema.util.MiscSchemaUtil; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SelectorQualifiedGetOptionsType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; - -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import javax.xml.namespace.QName; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ResolveReferenceActionExpressionType; /** * Resolves a reference, e.g. a linkRef into a set of accounts. - * - * @author mederly */ @Component public class ResolveExecutor extends BaseActionExecutor { - private static final Trace LOGGER = TraceManager.getTrace(ResolveExecutor.class); - private static final String NAME = "resolve"; private static final String PARAM_NO_FETCH = "noFetch"; @PostConstruct public void init() { - scriptingExpressionEvaluator.registerActionExecutor(NAME, this); + actionExecutorRegistry.register(NAME, ResolveReferenceActionExpressionType.class, this); } @Override - public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { + public PipelineData execute(ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException, SchemaException, ConfigurationException, + ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException { - boolean noFetch = expressionHelper.getArgumentAsBoolean(expression.getParameter(), PARAM_NO_FETCH, input, context, false, NAME, globalResult); + Collection> options; + if (action instanceof ResolveReferenceActionExpressionType) { + SelectorQualifiedGetOptionsType optionsBean = ((ResolveReferenceActionExpressionType) action).getOptions(); + options = MiscSchemaUtil.optionsTypeToOptions(optionsBean, prismContext); + } else { + boolean noFetch = expressionHelper.getArgumentAsBoolean(action.getParameter(), PARAM_NO_FETCH, input, context, false, NAME, globalResult); + options = schemaHelper.getOperationOptionsBuilder().noFetch(noFetch).build(); + } PipelineData output = PipelineData.createEmpty(); - for (PipelineItem item: input.getData()) { - PrismValue value = item.getValue(); - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); - context.checkTaskStop(); - if (value instanceof PrismReferenceValue) { - PrismReferenceValue prismReferenceValue = (PrismReferenceValue) value; - String oid = prismReferenceValue.getOid(); - QName targetTypeQName = prismReferenceValue.getTargetType(); - if (targetTypeQName == null) { - throw new ScriptExecutionException("Couldn't resolve reference, because target type is unknown: " + prismReferenceValue); - } - Class typeClass = prismContext.getSchemaRegistry().determineCompileTimeClass(targetTypeQName); - if (typeClass == null) { - throw new ScriptExecutionException("Couldn't resolve reference, because target type class is unknown for target type " + targetTypeQName); - } - try { - PrismObjectValue resolved = operationsHelper.getObject(typeClass, oid, noFetch, context, result).getValue(); - output.add(new PipelineItem(resolved, item.getResult())); - } catch (Throwable e) { - //noinspection ThrowableNotThrown - processActionException(e, NAME, value, context); - output.add(item); // to keep track of failed item (may trigger exceptions downstream) - } - } else { + iterateOverItems(input, context, globalResult, + (value, item, result) -> + resolveReference(context, options, output, item, value, result), + (value, exception) -> + context.println("Couldn't resolve reference: " + value + exceptionSuffix(exception))); + + return output; + } + + private void resolveReference(ExecutionContext context, Collection> options, + PipelineData output, PipelineItem item, PrismValue value, OperationResult result) throws ScriptExecutionException { + if (value instanceof PrismReferenceValue) { + PrismReferenceValue prismReferenceValue = (PrismReferenceValue) value; + String oid = prismReferenceValue.getOid(); + QName targetTypeQName = prismReferenceValue.getTargetType(); + if (targetTypeQName == null) { + throw new ScriptExecutionException("Couldn't resolve reference, because target type is unknown: " + prismReferenceValue); + } + Class type = prismContext.getSchemaRegistry().determineCompileTimeClass(targetTypeQName); + if (type == null) { + throw new ScriptExecutionException("Couldn't resolve reference, because target type class is unknown for target type " + targetTypeQName); + } + try { + PrismObjectValue resolved = modelService.getObject(type, oid, options, context.getTask(), result).getValue(); + output.add(new PipelineItem(resolved, item.getResult())); + } catch (Throwable e) { //noinspection ThrowableNotThrown - processActionException(new ScriptExecutionException("Item is not a PrismReference"), NAME, value, context); + processActionException(e, NAME, value, context); + output.add(item); // to keep track of failed item (may trigger exceptions downstream) } - operationsHelper.trimAndCloneResult(result, globalResult, context); + } else { + //noinspection ThrowableNotThrown + processActionException(new ScriptExecutionException("Value is not a reference"), NAME, value, context); + output.add(item); // to keep track of failed item (may trigger exceptions downstream) } - return output; + } + + @Override + String getActionName() { + return NAME; } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ResumeExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ResumeExecutor.java deleted file mode 100644 index 77c7b477456..00000000000 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ResumeExecutor.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.model.impl.scripting.actions; - -import com.evolveum.midpoint.model.api.PipelineItem; -import com.evolveum.midpoint.model.api.ScriptExecutionException; -import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; -import com.evolveum.midpoint.model.impl.scripting.PipelineData; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectValue; -import com.evolveum.midpoint.prism.PrismValue; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -import static java.util.Collections.singleton; - -/** - * @author mederly - */ -@Component -public class ResumeExecutor extends BaseActionExecutor { - - //private static final Trace LOGGER = TraceManager.getTrace(ResumeExecutor.class); - - private static final String NAME = "resume"; - - @PostConstruct - public void init() { - scriptingExpressionEvaluator.registerActionExecutor(NAME, this); - } - - @Override - public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { - - for (PipelineItem item: input.getData()) { - PrismValue value = item.getValue(); - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); - context.checkTaskStop(); - if (value instanceof PrismObjectValue) { - @SuppressWarnings({"unchecked", "raw"}) - PrismObject prismObject = ((PrismObjectValue) value).asPrismObject(); - ObjectType object = prismObject.asObjectable(); - if (object instanceof TaskType) { - long started = operationsHelper.recordStart(context, object); - Throwable exception = null; - try { - taskService.resumeTasks(singleton(object.getOid()), context.getTask(), result); - operationsHelper.recordEnd(context, object, started, null); - } catch (Throwable ex) { - operationsHelper.recordEnd(context, object, started, ex); - exception = processActionException(ex, NAME, value, context); - } - context.println((exception != null ? "Attempted to resume " : "Resumed ") + prismObject.toString() + exceptionSuffix(exception)); - } else { - //noinspection ThrowableNotThrown - processActionException(new ScriptExecutionException("Item is not a task"), NAME, value, context); - } - } else { - //noinspection ThrowableNotThrown - processActionException(new ScriptExecutionException("Item is not a PrismObject"), NAME, value, context); - } - operationsHelper.trimAndCloneResult(result, globalResult, context); - } - return input; - } -} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ResumeTaskExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ResumeTaskExecutor.java new file mode 100644 index 00000000000..f9e35cc9bfc --- /dev/null +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ResumeTaskExecutor.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.model.impl.scripting.actions; + +import static java.util.Collections.singleton; + +import javax.annotation.PostConstruct; + +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.model.api.ScriptExecutionException; +import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; +import com.evolveum.midpoint.model.impl.scripting.PipelineData; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ResumeTaskActionExpressionType; + +/** + * Executes "resume" action. + */ +@Component +public class ResumeTaskExecutor extends AbstractObjectBasedActionExecutor { + + private static final String NAME = "resume"; + + @PostConstruct + public void init() { + actionExecutorRegistry.register(NAME, ResumeTaskActionExpressionType.class, this); + } + + @Override + public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException { + + iterateOverObjects(input, context, globalResult, + (object, item, result) -> { + taskService.resumeTasks(singleton(object.getOid()), context.getTask(), result); + context.println("Resumed " + object); + }, (object, exception) -> + context.println("Failed to resume " + object + exceptionSuffix(exception)) + ); + return input; + } + + @Override + String getActionName() { + return NAME; + } + + @Override + Class getObjectType() { + return TaskType.class; + } +} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ScriptExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ScriptExecutor.java deleted file mode 100644 index f24b1fc49a4..00000000000 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ScriptExecutor.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.model.impl.scripting.actions; - -import com.evolveum.midpoint.model.api.PipelineItem; -import com.evolveum.midpoint.model.api.ScriptExecutionException; -import com.evolveum.midpoint.model.common.expression.script.ScriptExpression; -import com.evolveum.midpoint.model.common.expression.script.ScriptExpressionFactory; -import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; -import com.evolveum.midpoint.model.impl.scripting.PipelineData; -import com.evolveum.midpoint.model.impl.util.ModelImplUtils; -import com.evolveum.midpoint.prism.*; -import com.evolveum.midpoint.repo.common.expression.ExpressionFactory; -import com.evolveum.midpoint.repo.common.expression.ExpressionSyntaxException; -import com.evolveum.midpoint.repo.common.expression.ExpressionUtil; -import com.evolveum.midpoint.repo.common.expression.ExpressionVariables; -import com.evolveum.midpoint.schema.constants.ExpressionConstants; -import com.evolveum.midpoint.schema.expression.ExpressionProfile; -import com.evolveum.midpoint.schema.expression.TypedValue; -import com.evolveum.midpoint.schema.expression.VariablesMap; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.util.QNameUtil; -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.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.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ScriptExpressionEvaluatorType; -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; -import org.apache.commons.lang3.StringUtils; -import org.jetbrains.annotations.NotNull; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import javax.xml.namespace.QName; -import java.util.Collection; -import java.util.List; - -import static com.evolveum.midpoint.model.impl.scripting.VariablesUtil.cloneIfNecessary; - -/** - * @author mederly - */ -@Component -public class ScriptExecutor extends BaseActionExecutor { - - //private static final Trace LOGGER = TraceManager.getTrace(ScriptExecutor.class); - - @Autowired private ScriptExpressionFactory scriptExpressionFactory; - @Autowired private ExpressionFactory expressionFactory; - - private static final String NAME = "execute-script"; - private static final String PARAM_SCRIPT = "script"; - private static final String PARAM_QUIET = "quiet"; // todo implement for other actions as well - private static final String PARAM_OUTPUT_ITEM = "outputItem"; // item name or type (as URI!) -- EXPERIMENTAL - private static final String PARAM_FOR_WHOLE_INPUT = "forWholeInput"; - - @PostConstruct - public void init() { - scriptingExpressionEvaluator.registerActionExecutor(NAME, this); - } - - @Override - public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { - - checkRootAuthorization(context, globalResult, NAME); - - ScriptExpressionEvaluatorType script = expressionHelper.getSingleArgumentValue(expression.getParameter(), PARAM_SCRIPT, true, true, - NAME, input, context, ScriptExpressionEvaluatorType.class, globalResult); - String outputItem = expressionHelper.getSingleArgumentValue(expression.getParameter(), PARAM_OUTPUT_ITEM, false, false, - NAME, input, context, String.class, globalResult); - boolean forWholeInput = expressionHelper.getArgumentAsBoolean(expression.getParameter(), PARAM_FOR_WHOLE_INPUT, input, context, false, PARAM_FOR_WHOLE_INPUT, globalResult); - boolean quiet = expressionHelper.getArgumentAsBoolean(expression.getParameter(), PARAM_QUIET, input, context, false, PARAM_QUIET, globalResult); - - ItemDefinition outputDefinition = getItemDefinition(outputItem); - ExpressionProfile expressionProfile = null; // TODO - - ScriptExpression scriptExpression; - try { - scriptExpression = scriptExpressionFactory.createScriptExpression(script, outputDefinition, expressionProfile, expressionFactory, "script", - globalResult); - } catch (ExpressionSyntaxException | SecurityViolationException e) { - throw new ScriptExecutionException("Couldn't parse script expression: " + e.getMessage(), e); - } - - PipelineData output = PipelineData.createEmpty(); - - if (forWholeInput) { - OperationResult result = operationsHelper.createActionResult(null, this, context, globalResult); - context.checkTaskStop(); - Throwable exception = null; - try { - TypedValue inputTypedValue = new TypedValue<>(input, PipelineData.class); - Object outObject = executeScript(scriptExpression, inputTypedValue, context.getInitialVariables(), context, result); - if (outObject != null) { - addToData(outObject, PipelineData.newOperationResult(), output); - } else { - // no definition means we don't plan to provide any output - so let's just copy the input item to the output - // (actually, null definition with non-null outObject should not occur) - if (outputDefinition == null) { - output.addAllFrom(input); - } - } - } catch (Throwable ex) { - exception = processActionException(ex, NAME, null, context); // TODO value for error reporting (3rd parameter) - } - if (!quiet) { - context.println((exception != null ? "Attempted to execute " : "Executed ") - + "script on the pipeline" + exceptionSuffix(exception)); - } - operationsHelper.trimAndCloneResult(result, globalResult, context); - } else { - for (PipelineItem item : input.getData()) { - PrismValue value = item.getValue(); - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); - - context.checkTaskStop(); - String valueDescription; - long started; - if (value instanceof PrismObjectValue) { - started = operationsHelper.recordStart(context, asObjectType(value)); - valueDescription = asObjectType(value).asPrismObject().toString(); - } else { - started = 0; - valueDescription = value.toHumanReadableString(); - } - Throwable exception = null; - try { - // Hack. TODO: we need to add definitions to Pipeline items. - TypedValue typedValue = new TypedValue(value, value == null ? Object.class : value.getClass()); - Object outObject = executeScript(scriptExpression, typedValue, item.getVariables(), context, result); - if (outObject != null) { - addToData(outObject, item.getResult(), output); - } else { - // no definition means we don't plan to provide any output - so let's just copy the input item to the output - // (actually, null definition with non-null outObject should not occur) - if (outputDefinition == null) { - output.add(item); - } - } - if (value instanceof PrismObjectValue) { - operationsHelper.recordEnd(context, asObjectType(value), started, null); - } - } catch (Throwable ex) { - if (value instanceof PrismObjectValue) { - operationsHelper.recordEnd(context, asObjectType(value), started, ex); - } - exception = processActionException(ex, NAME, value, context); - } - if (!quiet) { - context.println((exception != null ? "Attempted to execute " : "Executed ") - + "script on " + valueDescription + exceptionSuffix(exception)); - } - operationsHelper.trimAndCloneResult(result, globalResult, context); - } - } - return output; - } - - private void addToData(@NotNull Object outObject, @NotNull OperationResult result, PipelineData output) throws SchemaException { - if (outObject instanceof Collection) { - for (Object o : (Collection) outObject) { - addToData(o, result, output); - } - } else { - PrismValue value; - if (outObject instanceof PrismValue) { - value = (PrismValue) outObject; - } else if (outObject instanceof Objectable) { - value = prismContext.itemFactory().createObjectValue((Objectable) outObject); - } else if (outObject instanceof Containerable) { - value = prismContext.itemFactory().createContainerValue((Containerable) outObject); - } else { - value = prismContext.itemFactory().createPropertyValue(outObject); - } - output.add(new PipelineItem(value, result)); - } - } - - private ItemDefinition getItemDefinition(String itemUri) throws ScriptExecutionException { - if (StringUtils.isBlank(itemUri)) { - return null; - } - - QName itemName = QNameUtil.uriToQName(itemUri, true); - ItemDefinition def = prismContext.getSchemaRegistry().findItemDefinitionByElementName(itemName); - if (def != null) { - return def; - } - def = prismContext.getSchemaRegistry().findItemDefinitionByType(itemName); - if (def != null) { - return def; - } - throw new ScriptExecutionException("Supplied item identification " + itemUri + " corresponds neither to item name nor type name"); - } - - private Object executeScript(ScriptExpression scriptExpression, TypedValue inputTypedValue, - VariablesMap externalVariables, ExecutionContext context, OperationResult result) - throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, SecurityViolationException { - ExpressionVariables variables = new ExpressionVariables(); - variables.put(ExpressionConstants.VAR_INPUT, inputTypedValue); - variables.put(ExpressionConstants.VAR_PRISM_CONTEXT, prismContext, PrismContext.class); - ExpressionUtil.addActorVariable(variables, securityContextManager, prismContext); - externalVariables.forEach((k, v) -> variables.put(k, cloneIfNecessary(k, v))); - variables.registerAliasesFrom(externalVariables); - - List rv = ModelImplUtils.evaluateScript(scriptExpression, null, variables, true, "in '"+NAME+"' action", context.getTask(), result); - - if (rv == null || rv.size() == 0) { - return null; - } else if (rv.size() == 1) { - return rv.get(0); - } else { - return rv; // shouldn't occur; would cause problems - } - } - - private ObjectType asObjectType(PrismValue value) { - return (ObjectType) ((PrismObjectValue) value).asObjectable(); - } - -} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/TestResourceExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/TestResourceExecutor.java index 96559920918..02ac3da5e3a 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/TestResourceExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/TestResourceExecutor.java @@ -7,76 +7,71 @@ package com.evolveum.midpoint.model.impl.scripting.actions; -import com.evolveum.midpoint.model.impl.scripting.PipelineData; -import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; -import com.evolveum.midpoint.model.api.ScriptExecutionException; +import javax.annotation.PostConstruct; + +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.model.api.PipelineItem; -import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.model.api.ScriptExecutionException; +import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; +import com.evolveum.midpoint.model.impl.scripting.PipelineData; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismObjectValue; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; - -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.TestResourceActionExpressionType; /** - * @author mederly + * Executes "test-resource" action. */ @Component -public class TestResourceExecutor extends BaseActionExecutor { - - private static final Trace LOGGER = TraceManager.getTrace(TestResourceExecutor.class); +public class TestResourceExecutor extends AbstractObjectBasedActionExecutor { private static final String NAME = "test-resource"; @PostConstruct public void init() { - scriptingExpressionEvaluator.registerActionExecutor(NAME, this); + actionExecutorRegistry.register(NAME, TestResourceActionExpressionType.class, this); } @Override - public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, OperationResult globalResult) throws ScriptExecutionException { + public PipelineData execute(ActionExpressionType expression, PipelineData input, ExecutionContext context, + OperationResult globalResult) throws ScriptExecutionException { PipelineData output = PipelineData.createEmpty(); - for (PipelineItem item: input.getData()) { - PrismValue value = item.getValue(); - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); - context.checkTaskStop(); - if (value instanceof PrismObjectValue && ((PrismObjectValue) value).asObjectable() instanceof ResourceType) { - PrismObject resourceTypePrismObject = ((PrismObjectValue) value).asPrismObject(); - ResourceType resourceType = resourceTypePrismObject.asObjectable(); - long started = operationsHelper.recordStart(context, resourceType); - Throwable exception = null; - OperationResult testResult; - try { - testResult = modelService.testResource(resourceTypePrismObject.getOid(), context.getTask()); - operationsHelper.recordEnd(context, resourceType, started, null); - } catch (ObjectNotFoundException|RuntimeException e) { - operationsHelper.recordEnd(context, resourceType, started, e); - exception = processActionException(e, NAME, value, context); - testResult = new OperationResult(TestResourceExecutor.class.getName() + ".testResource"); - testResult.recordFatalError(e); - } - result.addSubresult(testResult); - context.println("Tested " + resourceTypePrismObject + ": " + testResult.getStatus() + exceptionSuffix(exception)); - try { - PrismObjectValue resourceValue = operationsHelper.getObject(ResourceType.class, resourceTypePrismObject.getOid(), false, context, result).getValue(); - output.add(new PipelineItem(resourceValue, item.getResult())); - } catch (ExpressionEvaluationException e) { - throw new ScriptExecutionException("Error getting resource "+resourceTypePrismObject.getOid()+": "+e.getMessage(), e); - } - } else { - //noinspection ThrowableNotThrown - processActionException(new ScriptExecutionException("Item is not a PrismObject"), NAME, value, context); - } - operationsHelper.trimAndCloneResult(result, globalResult, context); - } + iterateOverObjects(input, context, globalResult, + (object, item, result) -> + test(object, output, item, context, result), + (object, exception) -> + context.println("Failed to test " + object + exceptionSuffix(exception)) + ); + return output; } + + private void test(PrismObject object, PipelineData output, PipelineItem item, ExecutionContext context, + OperationResult result) throws ObjectNotFoundException, ExpressionEvaluationException, ScriptExecutionException { + String oid = object.getOid(); + OperationResult testResult = modelService.testResource(oid, context.getTask()); + context.println("Tested " + object + ": " + testResult.getStatus()); + result.addSubresult(testResult); + + PrismObjectValue resourceAfter = operationsHelper.getObject(ResourceType.class, oid, + false, context, result).getValue(); + output.add(new PipelineItem(resourceAfter, item.getResult())); + } + + @Override + Class getObjectType() { + return ResourceType.class; + } + + @Override + String getActionName() { + return NAME; + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/UnassignExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/UnassignExecutor.java index ad5c4cb42d3..e2fe55519dd 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/UnassignExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/UnassignExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2019 Evolveum and contributors + * Copyright (c) 2020 Evolveum and contributors * * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. @@ -10,68 +10,136 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import javax.annotation.PostConstruct; import javax.xml.namespace.QName; +import com.evolveum.midpoint.model.api.ScriptExecutionException; +import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; +import com.evolveum.midpoint.model.impl.scripting.PipelineData; + +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.util.CloneUtil; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.exception.*; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; + +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.UnassignActionExpressionType; +import com.evolveum.prism.xml.ns._public.query_3.SearchFilterType; + import org.springframework.stereotype.Component; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentHolderType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; + +import static com.evolveum.midpoint.model.impl.scripting.actions.UnassignExecutor.*; /** - * + * Executor for "unassign" actions. */ @Component -public class UnassignExecutor extends AssignmentOperationsExecutor { +public class UnassignExecutor extends AssignmentOperationsExecutor { + + private static final Trace LOGGER = TraceManager.getTrace(UnassignExecutor.class); + + private static final String NAME = "unassign"; + + static class UnassignParameters extends AssignmentOperationsExecutor.Parameters { + // These come from dynamic parameters (~ legacy way) + private final Collection dynamicRoleRefs = new ArrayList<>(); + private final Collection dynamicResourceRefs = new ArrayList<>(); + private final Collection dynamicRelations = new ArrayList<>(); // used only with dynamicRoleRefs + // This one is defined statically (~ modern way) + private ObjectFilter staticFilter; + } + + @PostConstruct + public void init() { + actionExecutorRegistry.register(NAME, UnassignActionExpressionType.class, this); + } @Override - protected String getName() { - return AssignmentOperationsExecutor.UNASSIGN_NAME; + UnassignParameters parseParameters(ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult result) throws SchemaException, ScriptExecutionException, ObjectNotFoundException, + SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { + UnassignParameters parameters = new UnassignParameters(); + parameters.dynamicResourceRefs.addAll(getResourcesParameter(action, input, context, result)); + parameters.dynamicRoleRefs.addAll(getRolesParameter(action, input, context, result)); + parameters.dynamicRelations.addAll(getRelationsParameter(action, input, context, result)); + // This was the original behavior: if not specified, we look for org:default references. + if (parameters.dynamicRelations.isEmpty()) { + parameters.dynamicRelations.add(relationRegistry.getDefaultRelation()); + } + + if (action instanceof UnassignActionExpressionType) { + SearchFilterType filterBean = ((UnassignActionExpressionType) action).getFilter(); + if (filterBean != null) { + parameters.staticFilter = prismContext.getQueryConverter().parseFilter(filterBean, AssignmentType.class); + } + } + return parameters; } @Override - protected ObjectDelta createDelta(AssignmentHolderType object, Collection resources, - Collection roles, Collection relationSpecifications) throws SchemaException { + boolean checkParameters(UnassignParameters parameters, ExecutionContext context) { + if (parameters.dynamicRoleRefs.isEmpty() && parameters.dynamicResourceRefs.isEmpty() + && parameters.staticFilter == null) { + LOGGER.warn("There are no roles nor resources to unassign and no filter is specified"); + context.println("Warning: There are no roles nor resources to unassign and no filter is specified"); + return false; + } else { + return true; + } + } - List assignmentsToDelete = new ArrayList<>(); + @Override + protected ObjectDelta createDelta(AssignmentHolderType object, UnassignParameters parameters) + throws SchemaException { - for (AssignmentType oldAssignment : object.getAssignment()) { - ObjectReferenceType targetRef = oldAssignment.getTargetRef(); - if (targetRef != null) { - if (roles != null) { - outerloop: - for (ObjectReferenceType roleRef : roles) { - if (targetRef.getOid() != null && targetRef.getOid().equals(roleRef.getOid())) { - for (QName relationSpecification : relationSpecifications) { - if (prismContext.relationMatches(relationSpecification, targetRef.getRelation())) { - assignmentsToDelete.add(oldAssignment.clone()); - break outerloop; - } - } - } - } - } - } else if (oldAssignment.getConstruction() != null) { - if (resources != null) { - for (ObjectReferenceType resourceRefToUnassign : resources) { - ObjectReferenceType oldResourceRef = oldAssignment.getConstruction().getResourceRef(); - if (oldResourceRef != null && oldResourceRef.getOid() != null && - oldResourceRef.getOid().equals(resourceRefToUnassign.getOid())) { - assignmentsToDelete.add(oldAssignment.clone()); - break; - } - } - } + List assignmentsToDelete = new ArrayList<>(); + for (AssignmentType existingAssignment : object.getAssignment()) { + if (matches(existingAssignment, parameters)) { + assignmentsToDelete.add(existingAssignment); } } return prismContext.deltaFor(object.getClass()) .item(ItemPath.create(AssignmentHolderType.F_ASSIGNMENT)) - .deleteRealValues(assignmentsToDelete) + .deleteRealValues(CloneUtil.cloneCollectionMembers(assignmentsToDelete)) .asObjectDelta(object.getOid()); } + + @SuppressWarnings("SimplifiableIfStatement") + private boolean matches(AssignmentType existingAssignment, UnassignParameters parameters) throws SchemaException { + ObjectReferenceType targetRef = existingAssignment.getTargetRef(); + if (targetRef != null && matchesOid(targetRef.getOid(), parameters.dynamicRoleRefs) + && matchesRelation(targetRef.getRelation(), parameters.dynamicRelations)) { + return true; + } + ConstructionType construction = existingAssignment.getConstruction(); + if (construction != null && construction.getResourceRef() != null + && matchesOid(construction.getResourceRef().getOid(), parameters.dynamicResourceRefs)) { + return true; + } + return parameters.staticFilter != null + && parameters.staticFilter.match(existingAssignment.asPrismContainerValue(), matchingRuleRegistry); + } + + private boolean matchesOid(String existingOid, Collection refsToUnassign) { + return existingOid != null && + refsToUnassign.stream() + .anyMatch(ref -> existingOid.equals(ref.getOid())); + } + + private boolean matchesRelation(QName existingRelation, Collection relationsToUnassign) { + return relationsToUnassign.stream() + .anyMatch(relationToUnassign -> prismContext.relationMatches(relationToUnassign, existingRelation)); + } + + @Override + protected String getActionName() { + return NAME; + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ValidateExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ValidateExecutor.java index 0cb2cdefb8b..105b93ae023 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ValidateExecutor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/actions/ValidateExecutor.java @@ -28,7 +28,10 @@ import javax.annotation.PostConstruct; /** - * @author mederly + * Executes "validate" action. + * + * There is no static (typed) definition of this action yet. + * Also, this code is not refactored yet. */ @Component public class ValidateExecutor extends BaseActionExecutor { @@ -42,7 +45,7 @@ public class ValidateExecutor extends BaseActionExecutor { @PostConstruct public void init() { - scriptingExpressionEvaluator.registerActionExecutor(NAME, this); + actionExecutorRegistry.register(NAME, this); } @Override @@ -52,7 +55,7 @@ public PipelineData execute(ActionExpressionType expression, PipelineData input, for (PipelineItem item: input.getData()) { PrismValue value = item.getValue(); - OperationResult result = operationsHelper.createActionResult(item, this, context, globalResult); + OperationResult result = operationsHelper.createActionResult(item, this); context.checkTaskStop(); if (value instanceof PrismObjectValue && ((PrismObjectValue) value).asObjectable() instanceof ResourceType) { PrismObject resourceTypePrismObject = ((PrismObjectValue) value).asPrismObject(); @@ -78,8 +81,13 @@ public PipelineData execute(ActionExpressionType expression, PipelineData input, //noinspection ThrowableNotThrown processActionException(new ScriptExecutionException("Item is not a PrismObject"), NAME, value, context); } - operationsHelper.trimAndCloneResult(result, globalResult, context); + operationsHelper.trimAndCloneResult(result, globalResult); } return output; } + + @Override + String getActionName() { + return NAME; + } } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/expressions/SearchEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/expressions/SearchEvaluator.java index 5fe7b516c96..55146d1a654 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/expressions/SearchEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/expressions/SearchEvaluator.java @@ -40,7 +40,6 @@ import org.springframework.stereotype.Component; import javax.xml.bind.JAXBElement; -import javax.xml.namespace.QName; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -48,7 +47,7 @@ import static com.evolveum.midpoint.model.impl.scripting.VariablesUtil.cloneIfNecessary; /** - * @author mederly + * Evaluates "search" scripting expression. */ @Component public class SearchEvaluator extends BaseExpressionEvaluator { @@ -63,7 +62,7 @@ public class SearchEvaluator extends BaseExpressionEvaluator { public PipelineData evaluate(SearchExpressionType searchExpression, PipelineData input, ExecutionContext context, OperationResult globalResult) - throws ScriptExecutionException { + throws ScriptExecutionException, SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException { Validate.notNull(searchExpression.getType()); ExpressionProfile expressionProfile = MiscSchemaUtil.getExpressionProfile(); @@ -139,7 +138,7 @@ public PipelineData evaluate(SearchExpressionType searchE } globalResult.setSummarizeSuccesses(true); globalResult.summarize(); - } catch (ScriptExecutionException e) { + } catch (ScriptExecutionException | SchemaException | ConfigurationException | ObjectNotFoundException | CommunicationException | SecurityViolationException | ExpressionEvaluationException e) { // todo think about this if (context.isContinueOnAnyError()) { LoggingUtils.logUnexpectedException(LOGGER, "Exception when evaluating item from search result list.", e); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/ExpressionHelper.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/ExpressionHelper.java index 2ee087a9ed5..65456995718 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/ExpressionHelper.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/ExpressionHelper.java @@ -14,8 +14,11 @@ import com.evolveum.midpoint.model.impl.scripting.ScriptingExpressionEvaluator; import com.evolveum.midpoint.prism.PrismPropertyValue; import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.prism.path.ItemName; import com.evolveum.midpoint.prism.util.JavaTypeConverter; import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.exception.*; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionParameterValueType; import com.evolveum.prism.xml.ns._public.types_3.RawType; import org.apache.commons.lang.Validate; @@ -29,17 +32,12 @@ import java.util.List; /** - * @author mederly + * */ @Component public class ExpressionHelper { - @Autowired - private ScriptingExpressionEvaluator scriptingExpressionEvaluator; - - // public JAXBElement getArgument(ActionExpressionType actionExpression, String parameterName) throws ScriptExecutionException { - // return getArgument(actionExpression.getParameter(), parameterName, false, false, actionExpression.getType()); - // } + @Autowired private ScriptingExpressionEvaluator scriptingExpressionEvaluator; public ActionParameterValueType getArgument(List arguments, String parameterName, boolean required, boolean requiredNonNull, String context) throws ScriptExecutionException { @@ -64,18 +62,18 @@ public ActionParameterValueType getArgument(List argum } public String getArgumentAsString(List arguments, String argumentName, PipelineData input, ExecutionContext context, - String defaultValue, String contextName, OperationResult parentResult) throws ScriptExecutionException { + String defaultValue, String contextName, OperationResult parentResult) throws ScriptExecutionException, SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException { ActionParameterValueType parameterValue = getArgument(arguments, argumentName, false, false, contextName); if (parameterValue != null) { if (parameterValue.getScriptingExpression() != null) { PipelineData data = scriptingExpressionEvaluator.evaluateExpression(parameterValue.getScriptingExpression(), input, context, parentResult); if (data != null) { - return data.getDataAsSingleString(); + return data.getSingleValue(String.class); } } else if (parameterValue.getValue() != null) { - PipelineData data = scriptingExpressionEvaluator.evaluateConstantStringExpression((RawType) parameterValue.getValue(), context, parentResult); + PipelineData data = scriptingExpressionEvaluator.evaluateConstantStringExpression((RawType) parameterValue.getValue(), context); if (data != null) { - return data.getDataAsSingleString(); + return data.getSingleValue(String.class); } } else { throw new IllegalStateException("No expression nor value specified"); @@ -84,8 +82,31 @@ public String getArgumentAsString(List arguments, Stri return defaultValue; } + public T getActionArgument(Class clazz, ActionExpressionType action, ItemName staticName, String dynamicName, PipelineData input, ExecutionContext context, + T defaultValue, String contextName, OperationResult parentResult) throws ScriptExecutionException, SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException { + List arguments = action.getParameter(); + ActionParameterValueType dynamicValue = getArgument(arguments, dynamicName, false, false, contextName); + if (dynamicValue != null) { + if (dynamicValue.getScriptingExpression() != null) { + PipelineData data = scriptingExpressionEvaluator.evaluateExpression(dynamicValue.getScriptingExpression(), input, context, parentResult); + if (data != null) { + return data.getSingleValue(clazz); + } + } else if (dynamicValue.getValue() != null) { + return ScriptingDataUtil.getRealValue(dynamicValue.getValue(), clazz); + } else { + throw new IllegalStateException("No expression nor value specified in parameter '" + dynamicName + "'"); + } + } + T staticValue = ScriptingBeansUtil.getBeanPropertyValue(action, staticName.getLocalPart(), clazz); + if (staticValue != null) { + return staticValue; + } + return defaultValue; + } + public Boolean getArgumentAsBoolean(List arguments, String argumentName, PipelineData input, ExecutionContext context, - Boolean defaultValue, String contextName, OperationResult parentResult) throws ScriptExecutionException { + Boolean defaultValue, String contextName, OperationResult parentResult) throws ScriptExecutionException, SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { String stringValue = getArgumentAsString(arguments, argumentName, input, context, null, contextName, parentResult); if (stringValue == null) { return defaultValue; @@ -99,19 +120,19 @@ public Boolean getArgumentAsBoolean(List arguments, St } public PipelineData evaluateParameter(ActionParameterValueType parameter, @Nullable Class expectedClass, PipelineData input, ExecutionContext context, OperationResult result) - throws ScriptExecutionException { + throws ScriptExecutionException, SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException { Validate.notNull(parameter, "parameter"); if (parameter.getScriptingExpression() != null) { return scriptingExpressionEvaluator.evaluateExpression(parameter.getScriptingExpression(), input, context, result); } else if (parameter.getValue() != null) { - return scriptingExpressionEvaluator.evaluateConstantExpression((RawType) parameter.getValue(), expectedClass, context, "evaluating parameter " + parameter.getName(), result); + return scriptingExpressionEvaluator.evaluateConstantExpression((RawType) parameter.getValue(), expectedClass, context, "evaluating parameter " + parameter.getName()); } else { throw new IllegalStateException("No expression nor value specified"); } } public T getSingleArgumentValue(List arguments, String parameterName, boolean required, - boolean requiredNonNull, String context, PipelineData input, ExecutionContext executionContext, Class clazz, OperationResult result) throws ScriptExecutionException { + boolean requiredNonNull, String context, PipelineData input, ExecutionContext executionContext, Class clazz, OperationResult result) throws ScriptExecutionException, SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { ActionParameterValueType paramValue = getArgument(arguments, parameterName, required, requiredNonNull, context); if (paramValue == null) { return null; @@ -134,22 +155,22 @@ public T getSingleArgumentValue(List arguments, St @NotNull public Collection getArgumentValues(List arguments, String parameterName, boolean required, - boolean requiredNonNull, String context, PipelineData input, ExecutionContext executionContext, Class clazz, OperationResult result) throws ScriptExecutionException { + boolean requiredNonNull, String context, PipelineData input, ExecutionContext executionContext, Class clazz, + OperationResult result) throws ScriptExecutionException, SchemaException, ObjectNotFoundException, + SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { List rv = new ArrayList<>(); for (ActionParameterValueType paramValue : arguments) { if (parameterName.equals(paramValue.getName())) { if (paramValue.getScriptingExpression() != null || paramValue.getValue() != null) { - if (paramValue != null) { - PipelineData paramData = evaluateParameter(paramValue, clazz, input, executionContext, result); - for (PipelineItem item : paramData.getData()) { - PrismValue prismValue = item.getValue(); - if (!(prismValue instanceof PrismPropertyValue)) { - throw new ScriptExecutionException( - "A prism property value was expected in '" + parameterName + "' parameter. Got " + prismValue - .getClass().getName() + " instead."); - } else { - rv.add(JavaTypeConverter.convert(clazz, prismValue.getRealValue())); - } + PipelineData paramData = evaluateParameter(paramValue, clazz, input, executionContext, result); + for (PipelineItem item : paramData.getData()) { + PrismValue prismValue = item.getValue(); + if (!(prismValue instanceof PrismPropertyValue)) { + throw new ScriptExecutionException( + "A prism property value was expected in '" + parameterName + "' parameter. Got " + prismValue + .getClass().getName() + " instead."); + } else { + rv.add(JavaTypeConverter.convert(clazz, prismValue.getRealValue())); } } } else { @@ -161,7 +182,7 @@ public Collection getArgumentValues(List argume } } } - if (required) { + if (required && rv.isEmpty()) { throw new ScriptExecutionException("Required parameter " + parameterName + " not present in invocation of \"" + context + "\""); } else { return rv; diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/OperationsHelper.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/OperationsHelper.java index 8510f27ea5b..fa3bccea930 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/OperationsHelper.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/OperationsHelper.java @@ -10,6 +10,7 @@ import com.evolveum.midpoint.model.api.*; import com.evolveum.midpoint.model.impl.scripting.ActionExecutor; import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; +import com.evolveum.midpoint.model.impl.scripting.PipelineData; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ObjectDelta; @@ -32,15 +33,23 @@ import com.evolveum.midpoint.util.exception.SecurityViolationException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ModelExecuteOptionsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PartialProcessingOptionsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SelectorQualifiedGetOptionsType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.AbstractExecutionActionExpressionType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; + +import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.Collection; import java.util.Collections; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.PartialProcessingTypeType.SKIP; + /** * @author mederly */ @@ -49,9 +58,61 @@ public class OperationsHelper { private static final Trace LOGGER = TraceManager.getTrace(OperationsHelper.class); + private static final String PARAM_RAW = "raw"; + private static final String PARAM_DRY_RUN = "dryRun"; + private static final String PARAM_SKIP_APPROVALS = "skipApprovals"; + private static final String PARAM_OPTIONS = "options"; + @Autowired private ModelService modelService; @Autowired private ModelInteractionService modelInteractionService; @Autowired private PrismContext prismContext; + @Autowired private ExpressionHelper expressionHelper; + + public boolean getDryRun(ActionExpressionType action, PipelineData input, ExecutionContext context, OperationResult result) + throws ScriptExecutionException, SchemaException, ObjectNotFoundException, SecurityViolationException, + CommunicationException, ConfigurationException, ExpressionEvaluationException { + return expressionHelper.getActionArgument(Boolean.class, action, + AbstractExecutionActionExpressionType.F_DRY_RUN, PARAM_DRY_RUN, + input, context, false, PARAM_DRY_RUN, result); + } + + @NotNull + public ModelExecuteOptions getOptions(ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult result) throws ScriptExecutionException, SchemaException, ConfigurationException, + ObjectNotFoundException, CommunicationException, SecurityViolationException, ExpressionEvaluationException { + ModelExecuteOptions options = getRawOptions(action, input, context, result); + + // raw and skipApprovals are not part of static schema + Boolean raw = expressionHelper.getArgumentAsBoolean(action.getParameter(), PARAM_RAW, input, context, null, PARAM_RAW, result); + Boolean skipApprovals = expressionHelper.getArgumentAsBoolean(action.getParameter(), PARAM_SKIP_APPROVALS, input, context, null, PARAM_SKIP_APPROVALS, result); + + if (Boolean.TRUE.equals(raw)) { + options.setRaw(true); + } + if (Boolean.TRUE.equals(skipApprovals)) { + if (options.getPartialProcessing() != null) { + options.getPartialProcessing().setApprovals(SKIP); + } else { + options.setPartialProcessing(new PartialProcessingOptionsType().approvals(SKIP)); + } + } + return options; + } + + @NotNull + private ModelExecuteOptions getRawOptions(ActionExpressionType action, PipelineData input, ExecutionContext context, + OperationResult result) throws ScriptExecutionException, SchemaException, ObjectNotFoundException, + SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { + ModelExecuteOptionsType optionsBean = expressionHelper.getActionArgument(ModelExecuteOptionsType.class, action, + AbstractExecutionActionExpressionType.F_EXECUTE_OPTIONS, PARAM_OPTIONS, input, context, null, + "executeOptions", result); + if (optionsBean != null) { + return ModelExecuteOptions.fromModelExecutionOptionsType(optionsBean); + } else { + return new ModelExecuteOptions(); + } + } + public Collection> applyDelta(ObjectDelta delta, ExecutionContext context, OperationResult result) throws ScriptExecutionException { return applyDelta(delta, null, context, result); @@ -59,6 +120,7 @@ public Collection> applyDelta(ObjectD public Collection> applyDelta(ObjectDelta delta, ModelExecuteOptions options, ExecutionContext context, OperationResult result) throws ScriptExecutionException { try { + //noinspection unchecked return modelService.executeChanges(Collections.singleton(delta), options, context.getTask(), result); } catch (ObjectAlreadyExistsException|ObjectNotFoundException|SchemaException|ExpressionEvaluationException|CommunicationException|ConfigurationException|PolicyViolationException|SecurityViolationException e) { throw new ScriptExecutionException("Couldn't modify object: " + e.getMessage(), e); @@ -67,6 +129,7 @@ public Collection> applyDelta(ObjectD public Collection> applyDelta(ObjectDelta delta, ModelExecuteOptions options, boolean dryRun, ExecutionContext context, OperationResult result) throws ScriptExecutionException { try { + LOGGER.debug("Going to execute delta (raw={}):\n{}", dryRun, delta.debugDumpLazily()); if (dryRun) { modelInteractionService.previewChanges(Collections.singleton(delta), options, context.getTask(), result); return null; @@ -103,12 +166,6 @@ public PrismObject getObject(Class type, String oid } } - public ModelExecuteOptions createExecutionOptions(boolean raw) { - ModelExecuteOptions options = new ModelExecuteOptions(); - options.setRaw(raw); - return options; - } - public long recordStart(ExecutionContext context, ObjectType objectType) { long started = System.currentTimeMillis(); if (context.isRecordProgressAndIterationStatistics()) { @@ -149,8 +206,7 @@ public void recordEnd(ExecutionContext context, ObjectType objectType, long star } } - public OperationResult createActionResult(PipelineItem item, ActionExecutor executor, ExecutionContext context, - OperationResult globalResult) { + public OperationResult createActionResult(PipelineItem item, ActionExecutor executor) { OperationResult result = new OperationResult(executor.getClass().getName() + "." + "execute"); if (item != null) { result.addParam("value", String.valueOf(item.getValue())); @@ -159,11 +215,10 @@ public OperationResult createActionResult(PipelineItem item, ActionExecutor exec return result; } - public void trimAndCloneResult(OperationResult result, OperationResult globalResult, - ExecutionContext context) { + public void trimAndCloneResult(OperationResult result, OperationResult globalResult) { result.computeStatusIfUnknown(); // TODO make this configurable - result.getSubresults().forEach(s -> s.setMinor()); + result.getSubresults().forEach(OperationResult::setMinor); result.cleanupResult(); globalResult.addSubresult(result.clone()); } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/ScriptingBeansUtil.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/ScriptingBeansUtil.java new file mode 100644 index 00000000000..19af01dae0e --- /dev/null +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/ScriptingBeansUtil.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.model.impl.scripting.helpers; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import javax.xml.bind.JAXBElement; +import javax.xml.namespace.QName; + +import org.apache.commons.beanutils.MethodUtils; +import org.apache.commons.beanutils.PropertyUtils; + +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ObjectFactory; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ScriptingExpressionType; + +import org.apache.commons.lang3.StringUtils; + +/** + * Utility methods related to ScriptingExpressionType beans. + */ +public class ScriptingBeansUtil { + + private static final Trace LOGGER = TraceManager.getTrace(ScriptingBeansUtil.class); + + private static final Map, QName> ELEMENTS = new HashMap<>(); + + static { + ObjectFactory objectFactory = new ObjectFactory(); + + for (Method method : objectFactory.getClass().getDeclaredMethods()) { + if (method.getReturnType() == JAXBElement.class) { + JAXBElement jaxbElement; + try { + //noinspection unchecked + jaxbElement = (JAXBElement) method.invoke(objectFactory, new Object[1]); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new IllegalStateException("Couldn't execute " + method); + } + + QName elementName = jaxbElement.getName(); + Class elementType = jaxbElement.getDeclaredType(); + if (ELEMENTS.containsKey(elementType)) { + throw new IllegalStateException("More than one JAXBElement for " + elementType + ": " + + elementName + ", " + ELEMENTS.get(elementType)); + } else { + ELEMENTS.put(elementType, elementName); + } + } + } + LOGGER.trace("Map: {}", ELEMENTS); + } + + /** + * Sometimes we have to convert "bare" ScriptingExpressionType instance to the JAXBElement version, + * with the correct element name. + */ + public static JAXBElement toJaxbElement(T expression) { + QName qname = ELEMENTS.get(expression.getClass()); + if (qname != null) { + //noinspection unchecked + return new JAXBElement<>(qname, (Class) expression.getClass(), expression); + } else { + throw new IllegalArgumentException("Unsupported expression type: " + expression.getClass()); + } + } + + public static String getActionType(ActionExpressionType action) { + if (action.getType() != null) { + return action.getType(); + } else { + return toJaxbElement(action).getName().getLocalPart(); + } + } + + static T getBeanPropertyValue(ActionExpressionType action, String propertyName, Class clazz) throws SchemaException { + try { + try { + Object rawValue = PropertyUtils.getSimpleProperty(action, propertyName); + return ScriptingDataUtil.cast(rawValue, clazz); + } catch (NoSuchMethodException e) { + if (Boolean.class.equals(clazz)) { + // Note that getSimpleProperty looks for "getX" instead of our "isX" getter for Boolean (not boolean) props. + //noinspection unchecked + return (T) getBeanBooleanPropertyValue(action, propertyName); + } else { + // This can occur when dynamic parameters are used: the action is of generic type, not the specific one. + return null; + } + } + } catch (IllegalAccessException | InvocationTargetException e) { + throw new SchemaException("Couldn't access '" + propertyName + "' in '" + action + "'", e); + } + } + + private static Boolean getBeanBooleanPropertyValue(ActionExpressionType action, String propertyName) + throws IllegalAccessException, InvocationTargetException, SchemaException { + try { + String methodName = "is" + StringUtils.capitalize(propertyName); + Object rawValue = MethodUtils.invokeExactMethod(action, methodName, new Object[0]); + return ScriptingDataUtil.cast(rawValue, Boolean.class); + } catch (NoSuchMethodException e) { + // This can occur when dynamic parameters are used: the action is of generic type, not the specific one. + return null; + } + } +} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/ScriptingDataUtil.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/ScriptingDataUtil.java new file mode 100644 index 00000000000..092719e4a20 --- /dev/null +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/ScriptingDataUtil.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.model.impl.scripting.helpers; + +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.prism.xml.ns._public.types_3.RawType; + +/** + * Utility methods related to processing data objects. + */ +public class ScriptingDataUtil { + + public static T getRealValue(Object value, Class clazz) throws SchemaException { + if (value == null) { + return null; + } else if (value instanceof RawType) { + return ((RawType) value).getParsedRealValue(clazz); + } else if (value instanceof PrismValue) { + return getRealValue((PrismValue) value, clazz); + } else + return cast(value, clazz); + } + + public static T getRealValue(PrismValue prismValue, Class clazz) throws SchemaException { + if (prismValue == null) { + return null; + } else { + Object realValue = prismValue.getRealValue(); + if (realValue == null) { + throw new SchemaException("Real value of 'null' embedded in " + prismValue); + } else { + return cast(realValue, clazz); + } + } + } + + static T cast(Object value, Class expectedClass) throws SchemaException { + if (value == null) { + return null; + } else if (!expectedClass.isAssignableFrom(value.getClass())) { + throw new SchemaException("Expected '" + expectedClass.getName() + "' but got '" + value.getClass().getName() + "'"); + } else { + //noinspection unchecked + return (T) value; + } + } +} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/ScriptingJaxbUtil.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/ScriptingJaxbUtil.java deleted file mode 100644 index 80ed118b20a..00000000000 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/helpers/ScriptingJaxbUtil.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2010-2014 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.model.impl.scripting.helpers; - -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ActionExpressionType; -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ExpressionPipelineType; -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ExpressionSequenceType; -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.FilterExpressionType; -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ForeachExpressionType; -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ObjectFactory; -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ScriptingExpressionType; -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.SearchExpressionType; -import com.evolveum.midpoint.xml.ns._public.model.scripting_3.SelectExpressionType; - -import javax.xml.bind.JAXBElement; -import javax.xml.namespace.QName; -import java.util.HashMap; -import java.util.Map; - -/** - * @author mederly - */ -public class ScriptingJaxbUtil { - - private static Map, QName> elements = new HashMap<>(); - - private static ObjectFactory objectFactory = new ObjectFactory(); - - static { - elements.put(ExpressionPipelineType.class, objectFactory.createPipeline(null).getName()); - elements.put(ExpressionSequenceType.class, objectFactory.createSequence(null).getName()); - elements.put(ForeachExpressionType.class, objectFactory.createForeach(null).getName()); - elements.put(SelectExpressionType.class, objectFactory.createSelect(null).getName()); - elements.put(FilterExpressionType.class, objectFactory.createFilter(null).getName()); - elements.put(SearchExpressionType.class, objectFactory.createSearch(null).getName()); - elements.put(ActionExpressionType.class, objectFactory.createAction(null).getName()); - } - - /** - * Ugly hack ... sometimes we have to convert "bare" ScriptingExpressionType instance to the JAXBElement version, - * with the correct element name. - */ - @SuppressWarnings({"raw", "unchecked"}) - public static JAXBElement toJaxbElement(ScriptingExpressionType expressionType) { - QName qname = elements.get(expressionType.getClass()); - if (qname == null) { - throw new IllegalArgumentException("Unsupported expression type: " + expressionType.getClass()); - } - return new JAXBElement(qname, expressionType.getClass(), expressionType); - } - -} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/MidpointPasswordValidator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/MidpointPasswordValidator.java deleted file mode 100644 index c441f49031b..00000000000 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/MidpointPasswordValidator.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.model.impl.security; - -import org.apache.wss4j.common.ext.WSSecurityException; -import org.apache.wss4j.dom.handler.RequestData; -import org.apache.wss4j.dom.message.token.UsernameToken; -import org.apache.wss4j.dom.validate.Credential; -import org.apache.wss4j.dom.validate.UsernameTokenValidator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import com.evolveum.midpoint.model.api.authentication.GuiProfiledPrincipalManager; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.security.api.ConnectionEnvironment; -import com.evolveum.midpoint.security.api.MidPointPrincipal; -import com.evolveum.midpoint.util.exception.*; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; - -@Service -public class MidpointPasswordValidator extends UsernameTokenValidator { - - @Autowired private PasswordAuthenticationEvaluatorImpl passwdEvaluator; - @Autowired private GuiProfiledPrincipalManager userService; - - @Override - public Credential validate(Credential credential, RequestData data) throws WSSecurityException { - try { - Credential credentialToReturn = super.validate(credential, data); - recordAuthenticationSuccess(credential); - return credentialToReturn; - } catch (WSSecurityException ex) { - recordAuthenticationError(credential, ex); - throw ex; - } - } - - private void recordAuthenticationSuccess(Credential credential) throws WSSecurityException { - MidPointPrincipal principal = resolveMidpointPrincipal(credential); - ConnectionEnvironment connEnv = ConnectionEnvironment.create(SchemaConstants.CHANNEL_WEB_SERVICE_URI); - passwdEvaluator.recordPasswordAuthenticationSuccess(principal, connEnv, resolvePassword(principal)); - } - - private void recordAuthenticationError(Credential credential, WSSecurityException originEx) throws WSSecurityException { - - MidPointPrincipal principal = resolveMidpointPrincipal(credential); - - PasswordType passwordType = resolvePassword(principal); - - ConnectionEnvironment connEnv = ConnectionEnvironment.create(SchemaConstants.CHANNEL_WEB_SERVICE_URI); - - PasswordCredentialsPolicyType passwdPolicy = null; - - if (principal.getApplicableSecurityPolicy() != null) { - CredentialsPolicyType credentialsPolicyType = principal.getApplicableSecurityPolicy().getCredentials(); - passwdPolicy = credentialsPolicyType.getPassword(); - } - - passwdEvaluator.recordPasswordAuthenticationFailure(principal, connEnv, passwordType, passwdPolicy, originEx.getMessage()); - } - - private MidPointPrincipal resolveMidpointPrincipal(Credential credential) throws WSSecurityException { - UsernameToken usernameToken = credential.getUsernametoken(); - String username = usernameToken.getName(); - - try { - return userService.getPrincipal(username, UserType.class); - } catch (ObjectNotFoundException | SchemaException | CommunicationException | ConfigurationException | SecurityViolationException | ExpressionEvaluationException e) { - throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION, e); - } - } - - private PasswordType resolvePassword(MidPointPrincipal principal) { - FocusType user = principal.getFocus(); - PasswordType passwordType = null; - if (user.getCredentials() != null) { - passwordType = user.getCredentials().getPassword(); - } - - return passwordType; - } -} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/SecurityHelper.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/SecurityHelper.java index b9e4979d658..1fd054c9557 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/SecurityHelper.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/SecurityHelper.java @@ -1,354 +1,292 @@ -/* - * Copyright (c) 2015-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.model.impl.security; - -import javax.xml.datatype.Duration; -import javax.xml.soap.SOAPMessage; - -import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; -import com.evolveum.midpoint.model.api.ModelAuditRecorder; -import com.evolveum.midpoint.model.impl.lens.LensContext; -import com.evolveum.midpoint.model.impl.lens.LensProjectionContext; -import com.evolveum.midpoint.model.impl.util.AuditHelper; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.security.api.HttpConnectionInformation; -import com.evolveum.midpoint.security.enforcer.api.SecurityEnforcer; - -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; - -import org.apache.cxf.binding.soap.SoapMessage; -import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor; -import org.apache.wss4j.common.ext.WSSecurityException; -import org.apache.wss4j.dom.util.WSSecurityUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.evolveum.midpoint.audit.api.AuditEventRecord; -import com.evolveum.midpoint.audit.api.AuditEventStage; -import com.evolveum.midpoint.audit.api.AuditEventType; -import com.evolveum.midpoint.model.impl.ModelObjectResolver; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.xml.XmlTypeConverter; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.result.OperationResultStatus; -import com.evolveum.midpoint.security.api.ConnectionEnvironment; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.task.api.TaskManager; -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.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SecurityViolationException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; - -/** - * @author semancik - */ -@Component -public class SecurityHelper implements ModelAuditRecorder { - - private static final Trace LOGGER = TraceManager.getTrace(SecurityHelper.class); - - public static final String CONTEXTUAL_PROPERTY_AUDITED_NAME = SecurityHelper.class.getName() + ".audited"; - - @Autowired private TaskManager taskManager; - @Autowired private AuditHelper auditHelper; - @Autowired private ModelObjectResolver objectResolver; - @Autowired private SecurityEnforcer securityEnforcer; - @Autowired private PrismContext prismContext; - - @Override - public void auditLoginSuccess(@NotNull FocusType user, @NotNull ConnectionEnvironment connEnv) { - auditLogin(user.getName().getOrig(), user, connEnv, OperationResultStatus.SUCCESS, null); - } - - public void auditLoginSuccess(@NotNull NodeType node, @NotNull ConnectionEnvironment connEnv) { - auditLogin(node.getName().getOrig(), null, connEnv, OperationResultStatus.SUCCESS, null); - } - - @Override - public void auditLoginFailure(@Nullable String username, @Nullable FocusType focus, @NotNull ConnectionEnvironment connEnv, String message) { - auditLogin(username, focus, connEnv, OperationResultStatus.FATAL_ERROR, message); - } - - private void auditLogin(@Nullable String username, @Nullable FocusType focus, @NotNull ConnectionEnvironment connEnv, @NotNull OperationResultStatus status, - @Nullable String message) { - Task task = taskManager.createTaskInstance(); - task.setChannel(connEnv.getChannel()); - - LOGGER.debug("Login {} username={}, channel={}: {}", - status == OperationResultStatus.SUCCESS ? "success" : "failure", username, - connEnv.getChannel(), message); - - AuditEventRecord record = new AuditEventRecord(AuditEventType.CREATE_SESSION, AuditEventStage.REQUEST); - record.setParameter(username); - if (focus != null ) { - record.setInitiator(focus.asPrismObject()); - } - record.setTimestamp(System.currentTimeMillis()); - record.setOutcome(status); - record.setMessage(message); - storeConnectionEnvironment(record, connEnv); - - auditHelper.audit(record, null, task, new OperationResult(SecurityHelper.class.getName() + ".auditLogin")); - } - - @Override - public void auditLogout(ConnectionEnvironment connEnv, Task task) { - AuditEventRecord record = new AuditEventRecord(AuditEventType.TERMINATE_SESSION, AuditEventStage.REQUEST); - record.setInitiatorAndLoginParameter(task.getOwner()); - record.setTimestamp(System.currentTimeMillis()); - record.setOutcome(OperationResultStatus.SUCCESS); - storeConnectionEnvironment(record, connEnv); - auditHelper.audit(record, null, task, new OperationResult(SecurityHelper.class.getName() + ".auditLogout")); - } - - private void storeConnectionEnvironment(AuditEventRecord record, ConnectionEnvironment connEnv) { - record.setChannel(connEnv.getChannel()); - record.setSessionIdentifier(connEnv.getSessionId()); - HttpConnectionInformation connInfo = connEnv.getConnectionInformation(); - if (connInfo != null) { - record.setRemoteHostAddress(connInfo.getRemoteHostAddress()); - record.setHostIdentifier(connInfo.getLocalHostName()); - } - } - - public String getUsernameFromMessage(SOAPMessage saajSoapMessage) throws WSSecurityException { - if (saajSoapMessage == null) { - return null; - } - Element securityHeader = WSSecurityUtil.getSecurityHeader(saajSoapMessage.getSOAPPart(), ""); - return getUsernameFromSecurityHeader(securityHeader); - } - - private String getUsernameFromSecurityHeader(Element securityHeader) { - if (securityHeader == null) { - return null; - } - - String username = ""; - NodeList list = securityHeader.getChildNodes(); - int len = list.getLength(); - Node elem; - for (int i = 0; i < len; i++) { - elem = list.item(i); - if (elem.getNodeType() != Node.ELEMENT_NODE) { - continue; - } - if ("UsernameToken".equals(elem.getLocalName())) { - NodeList nodes = elem.getChildNodes(); - int len2 = nodes.getLength(); - for (int j = 0; j < len2; j++) { - Node elem2 = nodes.item(j); - if ("Username".equals(elem2.getLocalName())) { - username = elem2.getTextContent(); - } - } - } - } - return username; - } - - public SOAPMessage getSOAPMessage(SoapMessage msg) { - SAAJInInterceptor.INSTANCE.handleMessage(msg); - return msg.getContent(SOAPMessage.class); - } - - /** - * Returns security policy applicable for the specified user. It looks for organization and global policies and takes into account - * deprecated properties and password policy references. The resulting security policy has all the (non-deprecated) properties set. - * If there is also referenced value policy, it is will be stored as "object" in the value policy reference inside the - * returned security policy. - */ - public SecurityPolicyType locateSecurityPolicy(PrismObject focus, PrismObject systemConfiguration, - Task task, OperationResult result) throws SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException { - - SecurityPolicyType focusSecurityPolicy = locateFocusSecurityPolicy(focus, task, result); - if (focusSecurityPolicy != null) { - traceSecurityPolicy(focusSecurityPolicy, focus); - return focusSecurityPolicy; - } - - SecurityPolicyType globalSecurityPolicy = locateGlobalSecurityPolicy(focus, systemConfiguration, task, result); - if (globalSecurityPolicy != null) { - traceSecurityPolicy(globalSecurityPolicy, focus); - return globalSecurityPolicy; - } - - return null; - } - - public SecurityPolicyType locateFocusSecurityPolicy(PrismObject focus, Task task, - OperationResult result) throws SchemaException { - PrismObject orgSecurityPolicy = objectResolver.searchOrgTreeWidthFirstReference(focus, - o -> o.asObjectable().getSecurityPolicyRef(), "security policy", task, result); - LOGGER.trace("Found organization security policy: {}", orgSecurityPolicy); - if (orgSecurityPolicy != null) { - SecurityPolicyType orgSecurityPolicyType = orgSecurityPolicy.asObjectable(); - postProcessSecurityPolicy(orgSecurityPolicyType, task, result); - return orgSecurityPolicyType; - } else { - return null; - } - } - - public SecurityPolicyType locateGlobalSecurityPolicy(PrismObject focus, - PrismObject systemConfiguration, Task task, OperationResult result) - throws CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException { - if (systemConfiguration != null) { - return resolveGlobalSecurityPolicy(focus, systemConfiguration.asObjectable(), task, result); - } else { - return null; - } - } - - public SecurityPolicyType locateProjectionSecurityPolicy(RefinedObjectClassDefinition structuralObjectClassDefinition, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { - LOGGER.trace("Finishing loading of projection context: security policy"); - ObjectReferenceType securityPolicyRef = structuralObjectClassDefinition.getSecurityPolicyRef(); - if (securityPolicyRef == null || securityPolicyRef.getOid() == null) { - LOGGER.trace("Security policy not defined for the projection context."); - return loadProjectionLegacyPasswordPolicy(structuralObjectClassDefinition, task, result); - } - LOGGER.trace("Loading security policy {} from: {}", securityPolicyRef, structuralObjectClassDefinition); - SecurityPolicyType securityPolicy = objectResolver.resolve(securityPolicyRef, SecurityPolicyType.class, null, " projection security policy", task, result); - if (securityPolicy == null) { - LOGGER.debug("Security policy {} defined for the projection does not exist", securityPolicyRef); - return null; - } - postProcessSecurityPolicy(securityPolicy, task, result); - return securityPolicy; - } - - - private SecurityPolicyType loadProjectionLegacyPasswordPolicy(RefinedObjectClassDefinition structuralObjectClassDefinition, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { - ObjectReferenceType passwordPolicyRef = structuralObjectClassDefinition.getPasswordPolicy(); - if (passwordPolicyRef == null || passwordPolicyRef.getOid() == null) { - LOGGER.trace("Legacy password policy not defined for the projection context."); - return null; - } - LOGGER.trace("Loading legacy password policy {} from: {}", passwordPolicyRef, structuralObjectClassDefinition); - ValuePolicyType passwordPolicy = objectResolver.resolve(passwordPolicyRef, - ValuePolicyType.class, null, " projection legacy password policy ", task, result); - if (passwordPolicy == null) { - LOGGER.debug("Legacy password policy {} defined for the projection does not exist", passwordPolicyRef); - return null; - } - ObjectReferenceType dummyPasswordPolicyRef = new ObjectReferenceType(); - dummyPasswordPolicyRef.asReferenceValue().setObject(passwordPolicy.asPrismObject()); - PrismObject securityPolicy = prismContext.createObject(SecurityPolicyType.class); - securityPolicy.asObjectable() - .beginCredentials() - .beginPassword() - .valuePolicyRef(dummyPasswordPolicyRef); - return securityPolicy.asObjectable(); - } - - - private SecurityPolicyType resolveGlobalSecurityPolicy(PrismObject focus, - SystemConfigurationType systemConfiguration, Task task, OperationResult result) - throws CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException { - ObjectReferenceType globalSecurityPolicyRef = systemConfiguration.getGlobalSecurityPolicyRef(); - if (globalSecurityPolicyRef != null) { - try { - SecurityPolicyType globalSecurityPolicyType = objectResolver.resolve(globalSecurityPolicyRef, SecurityPolicyType.class, null, "global security policy reference in system configuration", task, result); - LOGGER.trace("Using global security policy: {}", globalSecurityPolicyType); - postProcessSecurityPolicy(globalSecurityPolicyType, task, result); - traceSecurityPolicy(globalSecurityPolicyType, focus); - return globalSecurityPolicyType; - } catch (ObjectNotFoundException | SchemaException e) { - LOGGER.error(e.getMessage(), e); - traceSecurityPolicy(null, focus); - return null; - } - } - - return null; - } - - private void traceSecurityPolicy(SecurityPolicyType securityPolicyType, PrismObject user) { - if (LOGGER.isTraceEnabled()) { - if (user != null) { - if (securityPolicyType == null) { - LOGGER.trace("Located security policy for {}: null", user); - } else { - LOGGER.trace("Located security policy for {}:\n{}", user, securityPolicyType.asPrismObject().debugDump(1)); - } - } else { - if (securityPolicyType == null) { - LOGGER.trace("Located global security policy null"); - } else { - LOGGER.trace("Located global security policy :\n{}", securityPolicyType.asPrismObject().debugDump(1)); - } - } - } - - } - - private void postProcessSecurityPolicy(SecurityPolicyType securityPolicyType, Task task, OperationResult result) { - CredentialsPolicyType creds = securityPolicyType.getCredentials(); - if (creds != null) { - PasswordCredentialsPolicyType passwd = creds.getPassword(); - if (passwd != null) { - postProcessPasswordCredentialPolicy(securityPolicyType, passwd, task, result); - } - for (NonceCredentialsPolicyType nonce: creds.getNonce()) { - postProcessCredentialPolicy(securityPolicyType, nonce, "nonce credential policy", task, result); - } - SecurityQuestionsCredentialsPolicyType securityQuestions = creds.getSecurityQuestions(); - if (securityQuestions != null) { - postProcessCredentialPolicy(securityPolicyType, securityQuestions, "security questions credential policy", task, result); - } - } - } - - private void postProcessPasswordCredentialPolicy(SecurityPolicyType securityPolicyType, PasswordCredentialsPolicyType passwd, Task task, OperationResult result) { - postProcessCredentialPolicy(securityPolicyType, passwd, "password credential policy", task, result); - } - - private ValuePolicyType postProcessCredentialPolicy(SecurityPolicyType securityPolicyType, CredentialPolicyType credPolicy, String credShortDesc, Task task, OperationResult result) { - ObjectReferenceType valuePolicyRef = credPolicy.getValuePolicyRef(); - if (valuePolicyRef == null) { - return null; - } - ValuePolicyType valuePolicyType; - try { - valuePolicyType = objectResolver.resolve(valuePolicyRef, ValuePolicyType.class, null, credShortDesc + " in " + securityPolicyType, task, result); - } catch (ObjectNotFoundException | SchemaException | CommunicationException | ConfigurationException | SecurityViolationException | ExpressionEvaluationException e) { - LOGGER.warn("{} {} referenced from {} was not found", credShortDesc, valuePolicyRef.getOid(), securityPolicyType); - return null; - } - valuePolicyRef.asReferenceValue().setObject(valuePolicyType.asPrismObject()); - return valuePolicyType; - } - - private SecurityPolicyType postProcessPasswordPolicy(ValuePolicyType passwordPolicyType) { - SecurityPolicyType securityPolicyType = new SecurityPolicyType(); - CredentialsPolicyType creds = new CredentialsPolicyType(); - PasswordCredentialsPolicyType passwd = new PasswordCredentialsPolicyType(); - ObjectReferenceType passwordPolicyRef = new ObjectReferenceType(); - passwordPolicyRef.asReferenceValue().setObject(passwordPolicyType.asPrismObject()); - passwd.setValuePolicyRef(passwordPolicyRef); - creds.setPassword(passwd); - securityPolicyType.setCredentials(creds); - return securityPolicyType; - } - - private Duration daysToDuration(int days) { - return XmlTypeConverter.createDuration((long) days * 1000 * 60 * 60 * 24); - } - - public SecurityEnforcer getSecurityEnforcer() { - return securityEnforcer; - } -} +/* + * Copyright (c) 2015-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.model.impl.security; + +import javax.xml.datatype.Duration; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.audit.api.AuditEventRecord; +import com.evolveum.midpoint.audit.api.AuditEventStage; +import com.evolveum.midpoint.audit.api.AuditEventType; +import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; +import com.evolveum.midpoint.model.api.ModelAuditRecorder; +import com.evolveum.midpoint.model.impl.ModelObjectResolver; +import com.evolveum.midpoint.model.impl.util.AuditHelper; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.xml.XmlTypeConverter; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.result.OperationResultStatus; +import com.evolveum.midpoint.security.api.ConnectionEnvironment; +import com.evolveum.midpoint.security.api.HttpConnectionInformation; +import com.evolveum.midpoint.security.enforcer.api.SecurityEnforcer; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.task.api.TaskManager; +import com.evolveum.midpoint.util.exception.*; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; + +/** + * @author semancik + */ +@Component +public class SecurityHelper implements ModelAuditRecorder { + + private static final Trace LOGGER = TraceManager.getTrace(SecurityHelper.class); + + @Autowired private TaskManager taskManager; + @Autowired private AuditHelper auditHelper; + @Autowired private ModelObjectResolver objectResolver; + @Autowired private SecurityEnforcer securityEnforcer; + @Autowired private PrismContext prismContext; + + @Override + public void auditLoginSuccess(@NotNull FocusType user, @NotNull ConnectionEnvironment connEnv) { + auditLogin(user.getName().getOrig(), user, connEnv, OperationResultStatus.SUCCESS, null); + } + + public void auditLoginSuccess(@NotNull NodeType node, @NotNull ConnectionEnvironment connEnv) { + auditLogin(node.getName().getOrig(), null, connEnv, OperationResultStatus.SUCCESS, null); + } + + @Override + public void auditLoginFailure(@Nullable String username, @Nullable FocusType focus, @NotNull ConnectionEnvironment connEnv, String message) { + auditLogin(username, focus, connEnv, OperationResultStatus.FATAL_ERROR, message); + } + + private void auditLogin(@Nullable String username, @Nullable FocusType focus, @NotNull ConnectionEnvironment connEnv, @NotNull OperationResultStatus status, + @Nullable String message) { + Task task = taskManager.createTaskInstance(); + task.setChannel(connEnv.getChannel()); + + LOGGER.debug("Login {} username={}, channel={}: {}", + status == OperationResultStatus.SUCCESS ? "success" : "failure", username, + connEnv.getChannel(), message); + + AuditEventRecord record = new AuditEventRecord(AuditEventType.CREATE_SESSION, AuditEventStage.REQUEST); + record.setParameter(username); + if (focus != null) { + record.setInitiator(focus.asPrismObject()); + } + record.setTimestamp(System.currentTimeMillis()); + record.setOutcome(status); + record.setMessage(message); + storeConnectionEnvironment(record, connEnv); + + auditHelper.audit(record, null, task, new OperationResult(SecurityHelper.class.getName() + ".auditLogin")); + } + + @Override + public void auditLogout(ConnectionEnvironment connEnv, Task task) { + AuditEventRecord record = new AuditEventRecord(AuditEventType.TERMINATE_SESSION, AuditEventStage.REQUEST); + record.setInitiatorAndLoginParameter(task.getOwner()); + record.setTimestamp(System.currentTimeMillis()); + record.setOutcome(OperationResultStatus.SUCCESS); + storeConnectionEnvironment(record, connEnv); + auditHelper.audit(record, null, task, new OperationResult(SecurityHelper.class.getName() + ".auditLogout")); + } + + private void storeConnectionEnvironment(AuditEventRecord record, ConnectionEnvironment connEnv) { + record.setChannel(connEnv.getChannel()); + record.setSessionIdentifier(connEnv.getSessionId()); + HttpConnectionInformation connInfo = connEnv.getConnectionInformation(); + if (connInfo != null) { + record.setRemoteHostAddress(connInfo.getRemoteHostAddress()); + record.setHostIdentifier(connInfo.getLocalHostName()); + } + } + + /** + * Returns security policy applicable for the specified user. It looks for organization and global policies and takes into account + * deprecated properties and password policy references. The resulting security policy has all the (non-deprecated) properties set. + * If there is also referenced value policy, it is will be stored as "object" in the value policy reference inside the + * returned security policy. + */ + public SecurityPolicyType locateSecurityPolicy(PrismObject focus, PrismObject systemConfiguration, + Task task, OperationResult result) throws SchemaException, CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException { + + SecurityPolicyType focusSecurityPolicy = locateFocusSecurityPolicy(focus, task, result); + if (focusSecurityPolicy != null) { + traceSecurityPolicy(focusSecurityPolicy, focus); + return focusSecurityPolicy; + } + + SecurityPolicyType globalSecurityPolicy = locateGlobalSecurityPolicy(focus, systemConfiguration, task, result); + if (globalSecurityPolicy != null) { + traceSecurityPolicy(globalSecurityPolicy, focus); + return globalSecurityPolicy; + } + + return null; + } + + public SecurityPolicyType locateFocusSecurityPolicy(PrismObject focus, Task task, + OperationResult result) throws SchemaException { + PrismObject orgSecurityPolicy = objectResolver.searchOrgTreeWidthFirstReference(focus, + o -> o.asObjectable().getSecurityPolicyRef(), "security policy", task, result); + LOGGER.trace("Found organization security policy: {}", orgSecurityPolicy); + if (orgSecurityPolicy != null) { + SecurityPolicyType orgSecurityPolicyType = orgSecurityPolicy.asObjectable(); + postProcessSecurityPolicy(orgSecurityPolicyType, task, result); + return orgSecurityPolicyType; + } else { + return null; + } + } + + public SecurityPolicyType locateGlobalSecurityPolicy(PrismObject focus, + PrismObject systemConfiguration, Task task, OperationResult result) + throws CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException { + if (systemConfiguration != null) { + return resolveGlobalSecurityPolicy(focus, systemConfiguration.asObjectable(), task, result); + } else { + return null; + } + } + + public SecurityPolicyType locateProjectionSecurityPolicy(RefinedObjectClassDefinition structuralObjectClassDefinition, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { + LOGGER.trace("Finishing loading of projection context: security policy"); + ObjectReferenceType securityPolicyRef = structuralObjectClassDefinition.getSecurityPolicyRef(); + if (securityPolicyRef == null || securityPolicyRef.getOid() == null) { + LOGGER.trace("Security policy not defined for the projection context."); + return loadProjectionLegacyPasswordPolicy(structuralObjectClassDefinition, task, result); + } + LOGGER.trace("Loading security policy {} from: {}", securityPolicyRef, structuralObjectClassDefinition); + SecurityPolicyType securityPolicy = objectResolver.resolve(securityPolicyRef, SecurityPolicyType.class, null, " projection security policy", task, result); + if (securityPolicy == null) { + LOGGER.debug("Security policy {} defined for the projection does not exist", securityPolicyRef); + return null; + } + postProcessSecurityPolicy(securityPolicy, task, result); + return securityPolicy; + } + + private SecurityPolicyType loadProjectionLegacyPasswordPolicy(RefinedObjectClassDefinition structuralObjectClassDefinition, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { + ObjectReferenceType passwordPolicyRef = structuralObjectClassDefinition.getPasswordPolicy(); + if (passwordPolicyRef == null || passwordPolicyRef.getOid() == null) { + LOGGER.trace("Legacy password policy not defined for the projection context."); + return null; + } + LOGGER.trace("Loading legacy password policy {} from: {}", passwordPolicyRef, structuralObjectClassDefinition); + ValuePolicyType passwordPolicy = objectResolver.resolve(passwordPolicyRef, + ValuePolicyType.class, null, " projection legacy password policy ", task, result); + if (passwordPolicy == null) { + LOGGER.debug("Legacy password policy {} defined for the projection does not exist", passwordPolicyRef); + return null; + } + ObjectReferenceType dummyPasswordPolicyRef = new ObjectReferenceType(); + dummyPasswordPolicyRef.asReferenceValue().setObject(passwordPolicy.asPrismObject()); + PrismObject securityPolicy = prismContext.createObject(SecurityPolicyType.class); + securityPolicy.asObjectable() + .beginCredentials() + .beginPassword() + .valuePolicyRef(dummyPasswordPolicyRef); + return securityPolicy.asObjectable(); + } + + private SecurityPolicyType resolveGlobalSecurityPolicy(PrismObject focus, + SystemConfigurationType systemConfiguration, Task task, OperationResult result) + throws CommunicationException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException { + ObjectReferenceType globalSecurityPolicyRef = systemConfiguration.getGlobalSecurityPolicyRef(); + if (globalSecurityPolicyRef != null) { + try { + SecurityPolicyType globalSecurityPolicyType = objectResolver.resolve(globalSecurityPolicyRef, SecurityPolicyType.class, null, "global security policy reference in system configuration", task, result); + LOGGER.trace("Using global security policy: {}", globalSecurityPolicyType); + postProcessSecurityPolicy(globalSecurityPolicyType, task, result); + traceSecurityPolicy(globalSecurityPolicyType, focus); + return globalSecurityPolicyType; + } catch (ObjectNotFoundException | SchemaException e) { + LOGGER.error(e.getMessage(), e); + traceSecurityPolicy(null, focus); + return null; + } + } + + return null; + } + + private void traceSecurityPolicy(SecurityPolicyType securityPolicyType, PrismObject user) { + if (LOGGER.isTraceEnabled()) { + if (user != null) { + if (securityPolicyType == null) { + LOGGER.trace("Located security policy for {}: null", user); + } else { + LOGGER.trace("Located security policy for {}:\n{}", user, securityPolicyType.asPrismObject().debugDump(1)); + } + } else { + if (securityPolicyType == null) { + LOGGER.trace("Located global security policy null"); + } else { + LOGGER.trace("Located global security policy :\n{}", securityPolicyType.asPrismObject().debugDump(1)); + } + } + } + + } + + private void postProcessSecurityPolicy(SecurityPolicyType securityPolicyType, Task task, OperationResult result) { + CredentialsPolicyType creds = securityPolicyType.getCredentials(); + if (creds != null) { + PasswordCredentialsPolicyType passwd = creds.getPassword(); + if (passwd != null) { + postProcessPasswordCredentialPolicy(securityPolicyType, passwd, task, result); + } + for (NonceCredentialsPolicyType nonce : creds.getNonce()) { + postProcessCredentialPolicy(securityPolicyType, nonce, "nonce credential policy", task, result); + } + SecurityQuestionsCredentialsPolicyType securityQuestions = creds.getSecurityQuestions(); + if (securityQuestions != null) { + postProcessCredentialPolicy(securityPolicyType, securityQuestions, "security questions credential policy", task, result); + } + } + } + + private void postProcessPasswordCredentialPolicy(SecurityPolicyType securityPolicyType, PasswordCredentialsPolicyType passwd, Task task, OperationResult result) { + postProcessCredentialPolicy(securityPolicyType, passwd, "password credential policy", task, result); + } + + private ValuePolicyType postProcessCredentialPolicy(SecurityPolicyType securityPolicyType, CredentialPolicyType credPolicy, String credShortDesc, Task task, OperationResult result) { + ObjectReferenceType valuePolicyRef = credPolicy.getValuePolicyRef(); + if (valuePolicyRef == null) { + return null; + } + ValuePolicyType valuePolicyType; + try { + valuePolicyType = objectResolver.resolve(valuePolicyRef, ValuePolicyType.class, null, credShortDesc + " in " + securityPolicyType, task, result); + } catch (ObjectNotFoundException | SchemaException | CommunicationException | ConfigurationException | SecurityViolationException | ExpressionEvaluationException e) { + LOGGER.warn("{} {} referenced from {} was not found", credShortDesc, valuePolicyRef.getOid(), securityPolicyType); + return null; + } + valuePolicyRef.asReferenceValue().setObject(valuePolicyType.asPrismObject()); + return valuePolicyType; + } + + private SecurityPolicyType postProcessPasswordPolicy(ValuePolicyType passwordPolicyType) { + SecurityPolicyType securityPolicyType = new SecurityPolicyType(); + CredentialsPolicyType creds = new CredentialsPolicyType(); + PasswordCredentialsPolicyType passwd = new PasswordCredentialsPolicyType(); + ObjectReferenceType passwordPolicyRef = new ObjectReferenceType(); + passwordPolicyRef.asReferenceValue().setObject(passwordPolicyType.asPrismObject()); + passwd.setValuePolicyRef(passwordPolicyRef); + creds.setPassword(passwd); + securityPolicyType.setCredentials(creds); + return securityPolicyType; + } + + private Duration daysToDuration(int days) { + return XmlTypeConverter.createDuration((long) days * 1000 * 60 * 60 * 24); + } + + public SecurityEnforcer getSecurityEnforcer() { + return securityEnforcer; + } +} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/SpringAuthenticationInjectorInterceptor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/SpringAuthenticationInjectorInterceptor.java deleted file mode 100644 index 70624446519..00000000000 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/SpringAuthenticationInjectorInterceptor.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.model.impl.security; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -import javax.xml.namespace.QName; -import javax.xml.soap.SOAPException; -import javax.xml.soap.SOAPMessage; - -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; - -import org.apache.commons.lang.StringUtils; -import org.apache.cxf.binding.soap.SoapMessage; -import org.apache.cxf.interceptor.Fault; -import org.apache.cxf.message.Message; -import org.apache.cxf.phase.Phase; -import org.apache.cxf.phase.PhaseInterceptor; -import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor; -import org.apache.ws.commons.schema.utils.DOMUtil; -import org.apache.wss4j.common.ext.WSSecurityException; -import org.apache.wss4j.common.ext.WSSecurityException.ErrorCode; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; - -import com.evolveum.midpoint.model.api.authentication.GuiProfiledPrincipalManager; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.security.api.AuthorizationConstants; -import com.evolveum.midpoint.security.api.ConnectionEnvironment; -import com.evolveum.midpoint.security.api.MidPointPrincipal; -import com.evolveum.midpoint.security.enforcer.api.AuthorizationParameters; -import com.evolveum.midpoint.security.enforcer.api.SecurityEnforcer; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.task.api.TaskManager; -import com.evolveum.midpoint.util.QNameUtil; -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.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SecurityViolationException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AuthorizationPhaseType; - -/** - * Responsible to inject Spring authentication object before we call WS method - */ -public class SpringAuthenticationInjectorInterceptor implements PhaseInterceptor { - - private static final String OPERATION_AUTHORIZATION = SpringAuthenticationInjectorInterceptor.class.getName() + ".authorization"; - - private static final Trace LOGGER = TraceManager.getTrace(SpringAuthenticationInjectorInterceptor.class); - - private String phase; - private Set before = new HashSet<>(); - private Set after = new HashSet<>(); - private String id; - - private GuiProfiledPrincipalManager guiProfiledPrincipalManager; - private SecurityEnforcer securityEnforcer; - private SecurityHelper securityHelper; - private TaskManager taskManager; - - public SpringAuthenticationInjectorInterceptor(GuiProfiledPrincipalManager guiProfiledPrincipalManager, - SecurityEnforcer securityEnforcer, SecurityHelper securityHelper, - TaskManager taskManager) { - super(); - this.guiProfiledPrincipalManager = guiProfiledPrincipalManager; - this.securityEnforcer = securityEnforcer; - this.securityHelper = securityHelper; - this.taskManager = taskManager; - id = getClass().getName(); - phase = Phase.PRE_PROTOCOL; - getAfter().add(WSS4JInInterceptor.class.getName()); - } - - @Override - public Set getAfter() { - return after; - } - - @Override - public Set getBefore() { - return before; - } - - @Override - public String getId() { - return id; - } - - @Override - public String getPhase() { - return phase; - } - - @Override - public Collection> getAdditionalInterceptors() { - return null; - } - - @Override - public void handleMessage(SoapMessage message) throws Fault { - //Note: in constructor we have specified that we will be called after we have been successfully authenticated the user through WS-Security - //Now we will only set the Spring Authentication object based on the user found in the header - LOGGER.trace("Intercepted message: {}", message); - SOAPMessage saajSoapMessage = securityHelper.getSOAPMessage(message); - if (saajSoapMessage == null) { - LOGGER.error("No soap message in handler"); - throw createFault(WSSecurityException.ErrorCode.FAILURE); - } - ConnectionEnvironment connEnv = ConnectionEnvironment.create(SchemaConstants.CHANNEL_WEB_SERVICE_URI); - String username = null; - try { - username = securityHelper.getUsernameFromMessage(saajSoapMessage); - LOGGER.trace("Attempt to authenticate user '{}'", username); - - if (StringUtils.isBlank(username)) { - message.put(SecurityHelper.CONTEXTUAL_PROPERTY_AUDITED_NAME, true); - securityHelper.auditLoginFailure(username, null, connEnv, "Empty username"); - throw createFault(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION); - } - - MidPointPrincipal principal = null; - try { - principal = guiProfiledPrincipalManager.getPrincipal(username, UserType.class); - } catch (SchemaException e) { - handlePrincipalException(message, username, connEnv, "Schema error", e); - } catch (CommunicationException e) { - handlePrincipalException(message, username, connEnv, "Communication error", e); - } catch (ConfigurationException e) { - handlePrincipalException(message, username, connEnv, "Configuration error", e); - } catch (SecurityViolationException e) { - handlePrincipalException(message, username, connEnv, "Security violation", e); - } catch (ExpressionEvaluationException e) { - handlePrincipalException(message, username, connEnv, "Expression error", e); - } - LOGGER.trace("Principal: {}", principal); - if (principal == null) { - message.put(SecurityHelper.CONTEXTUAL_PROPERTY_AUDITED_NAME, true); - securityHelper.auditLoginFailure(username, null, connEnv, "No user"); - throw createFault(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION); - } - - // Account validity and credentials and all this stuff should be already checked - // in the password callback - - Authentication authentication = new UsernamePasswordAuthenticationToken(principal, null); - SecurityContextHolder.getContext().setAuthentication(authentication); - - String operationName; - try { - operationName = DOMUtil.getFirstChildElement(saajSoapMessage.getSOAPBody()).getLocalName(); - } catch (SOAPException e) { - LOGGER.debug("Access to web service denied for user '{}': SOAP error: {}", - username, e.getMessage(), e); - message.put(SecurityHelper.CONTEXTUAL_PROPERTY_AUDITED_NAME, true); - securityHelper.auditLoginFailure(username, principal.getFocus(), connEnv, "SOAP error: "+e.getMessage()); - throw new Fault(e); - } - - // AUTHORIZATION - - Task task = taskManager.createTaskInstance(OPERATION_AUTHORIZATION); - OperationResult result = task.getResult(); - - boolean isAuthorized; - try { - isAuthorized = securityEnforcer.isAuthorized(AuthorizationConstants.AUTZ_WS_ALL_URL, AuthorizationPhaseType.REQUEST, AuthorizationParameters.EMPTY, null, task, result); - LOGGER.trace("Determined authorization for web service access (action: {}): {}", AuthorizationConstants.AUTZ_WS_ALL_URL, isAuthorized); - } catch (SchemaException | ObjectNotFoundException | ExpressionEvaluationException | CommunicationException | ConfigurationException | SecurityViolationException e) { - LOGGER.debug("Access to web service denied for user '{}': internal error: {}", - username, e.getMessage(), e); - message.put(SecurityHelper.CONTEXTUAL_PROPERTY_AUDITED_NAME, true); - securityHelper.auditLoginFailure(username, principal.getFocus(), connEnv, "Schema error: "+e.getMessage()); - throw createFault(WSSecurityException.ErrorCode.FAILURE); - } - if (!isAuthorized) { - String action = QNameUtil.qNameToUri(new QName(AuthorizationConstants.NS_AUTHORIZATION_WS, operationName)); - try { - isAuthorized = securityEnforcer.isAuthorized(action, AuthorizationPhaseType.REQUEST, AuthorizationParameters.EMPTY, null, task, result); - LOGGER.trace("Determined authorization for web service operation {} (action: {}): {}", operationName, action, isAuthorized); - } catch (SchemaException | ObjectNotFoundException | ExpressionEvaluationException | CommunicationException | ConfigurationException | SecurityViolationException e) { - LOGGER.debug("Access to web service denied for user '{}': schema error: {}", - username, e.getMessage(), e); - message.put(SecurityHelper.CONTEXTUAL_PROPERTY_AUDITED_NAME, true); - securityHelper.auditLoginFailure(username, principal.getFocus(), connEnv, "Internal error: "+e.getMessage()); - throw createFault(WSSecurityException.ErrorCode.FAILURE); - } - } - if (!isAuthorized) { - LOGGER.debug("Access to web service denied for user '{}': not authorized", username); - message.put(SecurityHelper.CONTEXTUAL_PROPERTY_AUDITED_NAME, true); - securityHelper.auditLoginFailure(username, principal.getFocus(), connEnv, "Not authorized"); - throw createFault(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION); - } - - } catch (WSSecurityException e) { - LOGGER.debug("Access to web service denied for user '{}': security exception: {}", - username, e.getMessage(), e); - message.put(SecurityHelper.CONTEXTUAL_PROPERTY_AUDITED_NAME, true); - securityHelper.auditLoginFailure(username, null, connEnv, "Security exception: "+e.getMessage()); - throw new Fault(e, e.getFaultCode()); - } catch (ObjectNotFoundException e) { - LOGGER.debug("Access to web service denied for user '{}': object not found: {}", - username, e.getMessage(), e); - message.put(SecurityHelper.CONTEXTUAL_PROPERTY_AUDITED_NAME, true); - securityHelper.auditLoginFailure(username, null, connEnv, "No user"); - throw createFault(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION); - } - - // Avoid auditing login attempt again if the operation fails on internal authorization - message.put(SecurityHelper.CONTEXTUAL_PROPERTY_AUDITED_NAME, true); - - LOGGER.debug("Access to web service allowed for user '{}'", username); - } - - private void handlePrincipalException(SoapMessage message, String username, ConnectionEnvironment connEnv, String errorDesc, Exception e) { - LOGGER.debug("Access to web service denied for user '{}': {}: {}", - username, errorDesc, e.getMessage(), e); - message.put(SecurityHelper.CONTEXTUAL_PROPERTY_AUDITED_NAME, true); - securityHelper.auditLoginFailure(username, null, connEnv, errorDesc + ": " + e.getMessage()); - throw new Fault(e); - } - - private Fault createFault(ErrorCode code) { - return new Fault(new WSSecurityException(code), code.getQName()); - } - - @Override - public void handleFault(SoapMessage message) { - // Nothing to do - } - -} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/SpringAuthenticationJanitorInterceptor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/SpringAuthenticationJanitorInterceptor.java deleted file mode 100644 index bb4345821cd..00000000000 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/SpringAuthenticationJanitorInterceptor.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2010-2014 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.model.impl.security; - -import org.apache.cxf.binding.soap.SoapMessage; -import org.apache.cxf.interceptor.Fault; -import org.apache.cxf.message.Message; -import org.apache.cxf.phase.Phase; -import org.apache.cxf.phase.PhaseInterceptor; -import org.springframework.security.core.context.SecurityContextHolder; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -/** - * Responsible to cleanup spring authentication object after we finished WS method call - */ -public class SpringAuthenticationJanitorInterceptor implements PhaseInterceptor { - - private String phase; - private Set before = new HashSet<>(); - private Set after = new HashSet<>(); - private String id; - - public SpringAuthenticationJanitorInterceptor() { - super(); - id = getClass().getName(); - phase = Phase.POST_INVOKE; - } - - @Override - public Set getAfter() { - return after; - } - - @Override - public Set getBefore() { - return before; - } - - @Override - public String getId() { - return id; - } - - @Override - public String getPhase() { - return phase; - } - - @Override - public Collection> getAdditionalInterceptors() { - return null; - } - - @Override - public void handleMessage(SoapMessage message) throws Fault { - SecurityContextHolder.getContext().setAuthentication(null); - } - - @Override - public void handleFault(SoapMessage message) { - } -} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/WsFaultListener.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/WsFaultListener.java deleted file mode 100644 index e10cd54f66d..00000000000 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/WsFaultListener.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2015-2016 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.model.impl.security; - -import javax.xml.soap.SOAPMessage; - -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.security.api.ConnectionEnvironment; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; - -import org.apache.cxf.logging.FaultListener; -import org.apache.cxf.message.Message; -import org.apache.wss4j.common.ext.WSSecurityException; - -public class WsFaultListener implements FaultListener { - - private static final Trace LOGGER = TraceManager.getTrace(WsFaultListener.class); - - private SecurityHelper securityHelper; - - public WsFaultListener(SecurityHelper securityHelper) { - super(); - this.securityHelper = securityHelper; - } - - @Override - public boolean faultOccurred(Exception exception, String description, Message message) { - LOGGER.trace("Handling fault: {}: {} - {}-{}", new Object[]{exception, description, message, exception}); - Object audited = message.getContextualProperty(SecurityHelper.CONTEXTUAL_PROPERTY_AUDITED_NAME); - if (audited != null && ((Boolean)audited)) { - return true; - } - if (exception instanceof PasswordCallbackException) { - return true; - } - if (exception.getCause() instanceof PasswordCallbackException) { - return true; - } - if (exception.getCause() != null && exception.getCause().getCause() instanceof PasswordCallbackException) { - return true; - } - try { - String auditMessage = exception.getMessage(); - if (exception.getClass() != null) { - // Exception cause has much better message because CXF masks real messages in the SOAP faults. - auditMessage = exception.getCause().getMessage(); - } - SOAPMessage saajSoapMessage = message.getContent(SOAPMessage.class); - String username = securityHelper.getUsernameFromMessage(saajSoapMessage); - ConnectionEnvironment connEnv = ConnectionEnvironment.create(SchemaConstants.CHANNEL_WEB_SERVICE_URI); - securityHelper.auditLoginFailure(username, null, connEnv, auditMessage); - } catch (WSSecurityException e) { - // Ignore - LOGGER.trace("Exception getting username from soap message (probably safe to ignore)", e); - } catch (Exception e) { - LOGGER.error("Error auditing SOAP fault: "+e.getMessage(), e); - // but otherwise ignore it - } - return true; - } - - -} diff --git a/model/model-impl/src/main/resources/ctx-model.xml b/model/model-impl/src/main/resources/ctx-model.xml index 2ae944e9fd9..c367c974e66 100644 --- a/model/model-impl/src/main/resources/ctx-model.xml +++ b/model/model-impl/src/main/resources/ctx-model.xml @@ -8,24 +8,17 @@ --> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:jaxrs="http://cxf.apache.org/jaxrs" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd + http://cxf.apache.org/jaxrs + http://cxf.apache.org/schemas/jaxrs.xsd" + default-lazy-init="false" + default-autowire="byName"> @@ -35,64 +28,63 @@ - - - - + + + + - + - - - + - - + + - + - - - + - - - - + + + + + - - - + + + + - - - - + + + + + - - - + + + + - + @@ -115,8 +107,8 @@ - + @@ -124,8 +116,8 @@ - + @@ -134,8 +126,8 @@ - + @@ -144,70 +136,58 @@ - - - - - - - + class="com.evolveum.midpoint.model.common.expression.evaluator.AssignmentTargetSearchExpressionEvaluatorFactory"> + + + + + + + - - - - - - - + class="com.evolveum.midpoint.model.common.expression.evaluator.ReferenceSearchExpressionEvaluatorFactory"> + + + + + + + - - - - - - - + class="com.evolveum.midpoint.model.common.expression.evaluator.AssociationTargetSearchExpressionEvaluatorFactory"> + + + + + + + - - - - - - + class="com.evolveum.midpoint.model.common.expression.evaluator.AssociationFromLinkExpressionEvaluatorFactory"> + + + + + + - - - - - - - + + + - - - + - + @@ -215,13 +195,11 @@ - + - - - + @@ -301,37 +279,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - @@ -364,46 +311,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/misc/TestTracing.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/misc/TestTracing.java new file mode 100644 index 00000000000..5d00a30b3c5 --- /dev/null +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/misc/TestTracing.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.model.intest.misc; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; + +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.testng.annotations.Test; + +import com.evolveum.midpoint.model.api.ModelExecuteOptions; +import com.evolveum.midpoint.model.intest.AbstractEmptyModelIntegrationTest; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.schema.SearchResultList; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.traces.TraceParser; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.test.DummyTestResource; +import com.evolveum.midpoint.test.TestResource; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; + +@ContextConfiguration(locations = { "classpath:ctx-model-intest-test-main.xml" }) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +public class TestTracing extends AbstractEmptyModelIntegrationTest { + + public static final File TEST_DIR = new File("src/test/resources/tracing"); + + private static final File SYSTEM_CONFIGURATION_FILE = new File(TEST_DIR, "system-configuration.xml"); + + private static final TestResource USER_JOE = new TestResource<>(TEST_DIR, "user-joe.xml", "c279c1c8-a160-4442-88b2-72b358e0c745"); + private static final TestResource ROLE_ILLEGAL = new TestResource<>(TEST_DIR, "role-illegal.xml", "13ca97ae-5919-42fb-91fb-cbc88704fd91"); + private static final DummyTestResource RESOURCE_ILLEGAL = new DummyTestResource(TEST_DIR, "resource-illegal.xml", "793bb9f5-edae-4251-bce7-4e99a72ac23f", "illegal"); + + @Override + public void initSystem(Task initTask, OperationResult initResult) + throws Exception { + super.initSystem(initTask, initResult); + + repoAdd(USER_JOE, initResult); + repoAdd(ROLE_ILLEGAL, initResult); + + initDummyResource(RESOURCE_ILLEGAL, initTask, initResult); + assertSuccess(modelService.testResource(RESOURCE_ILLEGAL.oid, initTask)); + } + + @Override + protected File getSystemConfigurationFile() { + return SYSTEM_CONFIGURATION_FILE; + } + + @Test + public void test100IllegalChars() throws Exception { + given(); + Task task = getTestTask(); + OperationResult result = getTestOperationResult(); + + when(); + ModelExecuteOptions options = new ModelExecuteOptions(); + options.setTracingProfile(createModelAndProvisioningLoggingTracingProfile()); + + ObjectDelta delta = deltaFor(UserType.class) + .item(UserType.F_ASSIGNMENT) + .add( + new AssignmentType(prismContext) + .targetRef(ROLE_ILLEGAL.oid, RoleType.COMPLEX_TYPE), + new AssignmentType(prismContext) + .beginConstruction() + .resourceRef(RESOURCE_ILLEGAL.oid, ResourceType.COMPLEX_TYPE) + .end() + ) + .asObjectDelta(USER_JOE.oid); + + executeChanges(delta, options, task, result); + + then(); + assertSuccess(result); + assertUserAfter(USER_JOE.oid) + .assignments() + .assertAssignments(2) + .end() + .links() + .assertLinks(1); + + RESOURCE_ILLEGAL.controller.assertAccountByUsername("joe") + .assertFullName("A\u0007B"); + + SearchResultList> reportOutputs = + repositoryService.searchObjects(ReportOutputType.class, null, null, result); + assertThat(reportOutputs.size()).as("# of report outputs").isEqualTo(1); + String file = reportOutputs.get(0).asObjectable().getFilePath(); + + TraceParser parser = new TraceParser(prismContext); + TracingOutputType parsed = parser.parse(new File(file)); + System.out.println("Tracing output parsed OK: " + parsed); + } +} diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/negative/TestModelWebServiceNegative.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/negative/TestModelWebServiceNegative.java deleted file mode 100644 index 80d89536b68..00000000000 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/negative/TestModelWebServiceNegative.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2010-2020 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.model.intest.negative; - -import java.io.File; -import java.util.Map; - -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.prism.marshaller.XNodeProcessorEvaluationMode; -import com.evolveum.midpoint.prism.xnode.PrimitiveXNode; -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.Test; - -import com.evolveum.midpoint.model.intest.AbstractInitializedModelIntegrationTest; -import com.evolveum.midpoint.prism.xnode.ValueParser; -import com.evolveum.midpoint.schema.constants.ObjectTypes; -import com.evolveum.midpoint.test.DummyResourceContoller; -import com.evolveum.midpoint.util.DOMUtil; -import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectDeltaListType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ModelExecuteOptionsType; -import com.evolveum.midpoint.xml.ns._public.common.fault_3.FaultMessage; -import com.evolveum.midpoint.xml.ns._public.common.fault_3.FaultType; -import com.evolveum.midpoint.xml.ns._public.common.fault_3.SchemaViolationFaultType; -import com.evolveum.prism.xml.ns._public.types_3.ChangeTypeType; -import com.evolveum.prism.xml.ns._public.types_3.ItemDeltaType; -import com.evolveum.prism.xml.ns._public.types_3.ItemPathType; -import com.evolveum.prism.xml.ns._public.types_3.ModificationTypeType; -import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; -import com.evolveum.prism.xml.ns._public.types_3.RawType; - -/** - * @author semancik - * - */ -@ContextConfiguration(locations = {"classpath:ctx-model-intest-test-main.xml"}) -@DirtiesContext(classMode = ClassMode.AFTER_CLASS) -public class TestModelWebServiceNegative extends AbstractInitializedModelIntegrationTest { - - public static final File TEST_DIR = new File("src/test/resources/crud"); - - /** - * First tests are positive, to make sure that this method works. - */ - @Test - public void test100ModifyAccountExplicitType() throws Exception { - // GIVEN - ObjectDeltaType objectChange = createShadowReplaceChange(ACCOUNT_SHADOW_GUYBRUSH_OID, - "attributes/"+DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_GOSSIP_NAME, - "foo", DOMUtil.XSD_STRING); - ObjectDeltaListType deltaList = new ObjectDeltaListType(); - deltaList.getDelta().add(objectChange); - - // WHEN - modelWeb.executeChanges(deltaList, null); - - // THEN - - // Check account in dummy resource - assertDefaultDummyAccount(ACCOUNT_GUYBRUSH_DUMMY_USERNAME, ACCOUNT_GUYBRUSH_DUMMY_FULLNAME, true); - assertDummyAccountAttribute(null, ACCOUNT_GUYBRUSH_DUMMY_USERNAME, - DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_GOSSIP_NAME, "foo"); - } - - /** - * First tests are positive, to make sure that this method works. - */ - @Test - public void test110ModifyAccountImplicitType() throws Exception { - // GIVEN - ObjectDeltaType objectChange = createShadowReplaceChange(ACCOUNT_SHADOW_GUYBRUSH_OID, - "attributes/"+DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_GOSSIP_NAME, - "bar", null); - ObjectDeltaListType deltaList = new ObjectDeltaListType(); - deltaList.getDelta().add(objectChange); - - // WHEN - modelWeb.executeChanges(deltaList, null); - - // THEN - - // Check account in dummy resource - assertDefaultDummyAccount(ACCOUNT_GUYBRUSH_DUMMY_USERNAME, ACCOUNT_GUYBRUSH_DUMMY_FULLNAME, true); - assertDummyAccountAttribute(null, ACCOUNT_GUYBRUSH_DUMMY_USERNAME, - DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_GOSSIP_NAME, "bar"); - } - - @Test - public void test200ModifyAccountWrongExplicitType() { - given(); - ObjectDeltaType objectChange = createShadowReplaceChange(ACCOUNT_SHADOW_GUYBRUSH_OID, - "attributes/"+DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_GOSSIP_NAME, - "42", DOMUtil.XSD_INT); - ObjectDeltaListType deltaList = new ObjectDeltaListType(); - deltaList.getDelta().add(objectChange); - - expect(); - assertExecuteChangesFailure(deltaList, null, SchemaViolationFaultType.class, "Expected", "but got class"); - } - - - private void assertExecuteChangesFailure( - ObjectDeltaListType deltaList, ModelExecuteOptionsType options, - Class expectedFaultTypeClass, String... messagePatterns) { - - try { - modelWeb.executeChanges(deltaList, options); - - AssertJUnit.fail("Unexpected success"); - } catch (FaultMessage f) { - FaultType faultInfo = f.getFaultInfo(); - if (expectedFaultTypeClass.isAssignableFrom(faultInfo.getClass())) { - // This is expected - String message = f.getMessage(); - for (String pattern: messagePatterns) { - if (!message.contains(pattern)) { - AssertJUnit.fail("Exception message does not contain pattern '"+pattern+"': "+message); - } - } - } else { - AssertJUnit.fail("Expected fault type of "+expectedFaultTypeClass+" but got "+faultInfo.getClass()); - } - } - } - - // TODO: more negative tests - - private ObjectDeltaType createShadowReplaceChange(String oid, String path, final String value, QName type) { - ObjectDeltaType objectChange = new ObjectDeltaType(); - objectChange.setOid(oid); - objectChange.setChangeType(ChangeTypeType.MODIFY); - objectChange.setObjectType(ObjectTypes.SHADOW.getTypeQName()); - ItemDeltaType itemDeltaType = new ItemDeltaType(); - itemDeltaType.setModificationType(ModificationTypeType.REPLACE); - ItemPathType itemPath = prismContext.itemPathParser().asItemPathType(path); - itemDeltaType.setPath(itemPath); - ValueParser valueParser = new ValueParser() { - @Override - public String parse(QName typeName, XNodeProcessorEvaluationMode mode) { - return value; - } - - @Override - public boolean canParseAs(QName typeName) { - return true; - } - - @Override - public boolean isEmpty() { - return false; - } - - @Override - public String getStringValue() { - return value; - } - - @Override - public Map getPotentiallyRelevantNamespaces() { - throw new UnsupportedOperationException(); - } - - @Override - public ValueParser freeze() { - return this; - } - }; - PrimitiveXNode xnode = prismContext.xnodeFactory().primitive(valueParser, type, type != null); - RawType rawValue = new RawType(xnode, prismContext); - itemDeltaType.getValue().add(rawValue); - objectChange.getItemDelta().add(itemDeltaType); - return objectChange; - } -} diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/scripting/TestScriptingBasic.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/scripting/AbstractBasicScriptingTest.java similarity index 66% rename from model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/scripting/TestScriptingBasic.java rename to model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/scripting/AbstractBasicScriptingTest.java index 58e56d53e8f..69917c4b0b8 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/scripting/TestScriptingBasic.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/scripting/AbstractBasicScriptingTest.java @@ -1,130 +1,153 @@ /* - * Copyright (c) 2010-2019 Evolveum and contributors + * Copyright (c) 2020 Evolveum and contributors * * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. */ package com.evolveum.midpoint.model.intest.scripting; +import static com.evolveum.midpoint.util.MiscUtil.emptyIfNull; + import static java.util.Collections.singleton; -import static org.apache.commons.collections4.CollectionUtils.emptyIfNull; import static org.assertj.core.api.Assertions.assertThat; import static org.testng.AssertJUnit.*; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.util.*; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import java.util.stream.Collectors; -import javax.xml.bind.JAXBException; import javax.xml.namespace.QName; +import com.evolveum.midpoint.model.api.ModelPublicConstants; import com.evolveum.midpoint.model.api.ScriptExecutionException; +import com.evolveum.midpoint.notifications.api.transports.Message; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.crypto.EncryptionException; +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.schema.constants.SchemaConstants; + +import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.util.exception.*; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; + +import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; +import org.testng.SkipException; import org.testng.annotations.Test; -import org.testng.collections.Sets; import com.evolveum.midpoint.common.LoggingConfigurationManager; -import com.evolveum.midpoint.model.api.ModelPublicConstants; import com.evolveum.midpoint.model.api.PipelineItem; -import com.evolveum.midpoint.model.impl.ModelWebService; import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; import com.evolveum.midpoint.model.impl.scripting.PipelineData; import com.evolveum.midpoint.model.impl.scripting.ScriptingExpressionEvaluator; import com.evolveum.midpoint.model.intest.AbstractInitializedModelIntegrationTest; -import com.evolveum.midpoint.notifications.api.transports.Message; -import com.evolveum.midpoint.prism.*; -import com.evolveum.midpoint.prism.crypto.EncryptionException; -import com.evolveum.midpoint.prism.delta.ItemDelta; -import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.path.ItemName; -import com.evolveum.midpoint.prism.util.PrismAsserts; -import com.evolveum.midpoint.schema.constants.RelationTypes; -import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.expression.VariablesMap; import com.evolveum.midpoint.schema.internals.InternalMonitor; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.result.OperationResultStatus; -import com.evolveum.midpoint.schema.util.ObjectQueryUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.test.util.LogfileTestTailer; -import com.evolveum.midpoint.test.util.MidPointAsserts; -import com.evolveum.midpoint.test.util.TestUtil; import com.evolveum.midpoint.util.DebugUtil; -import com.evolveum.midpoint.util.exception.*; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import com.evolveum.midpoint.xml.ns._public.model.scripting_3.*; -import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; + +import org.testng.collections.Sets; @ContextConfiguration(locations = { "classpath:ctx-model-intest-test-main.xml" }) @DirtiesContext(classMode = ClassMode.AFTER_CLASS) -public class TestScriptingBasic extends AbstractInitializedModelIntegrationTest { +public abstract class AbstractBasicScriptingTest extends AbstractInitializedModelIntegrationTest { public static final File TEST_DIR = new File("src/test/resources/scripting"); private static final File SYSTEM_CONFIGURATION_FILE = new File(TEST_DIR, "system-configuration.xml"); - private static final File LOG_FILE = new File(TEST_DIR, "log.xml"); + private static final ItemName USER_NAME_TASK_EXTENSION_PROPERTY = new ItemName("http://midpoint.evolveum.com/xml/ns/samples/piracy", "userName"); + private static final ItemName USER_DESCRIPTION_TASK_EXTENSION_PROPERTY = new ItemName("http://midpoint.evolveum.com/xml/ns/samples/piracy", "userDescription"); + private static final ItemName STUDY_GROUP_TASK_EXTENSION_PROPERTY = new ItemName("http://midpoint.evolveum.com/xml/ns/samples/piracy", "studyGroup"); + + // Tests 1xx + private static final String ECHO = "echo"; + private static final String LOG = "log"; + + // Tests 2xx: No "legacy" and "new" versions for these private static final File SEARCH_FOR_USERS_FILE = new File(TEST_DIR, "search-for-users.xml"); private static final File SEARCH_FOR_USERS_WITH_EXPRESSIONS_FILE = new File(TEST_DIR, "search-for-users-with-expressions.xml"); - private static final File SEARCH_FOR_USERS_RESOLVE_NAMES_FOR_ROLE_MEMBERSHIP_REF_FILE = new File(TEST_DIR, "search-for-users-resolve-names-for-roleMembershipRef.xml"); - private static final File SEARCH_FOR_USERS_RESOLVE_ROLE_MEMBERSHIP_REF_FILE = new File(TEST_DIR, "search-for-users-resolve-roleMembershipRef.xml"); private static final File SEARCH_FOR_SHADOWS_FILE = new File(TEST_DIR, "search-for-shadows.xml"); - private static final File SEARCH_FOR_SHADOWS_NOFETCH_FILE = new File(TEST_DIR, "search-for-shadows-nofetch.xml"); + private static final String SEARCH_FOR_SHADOWS_NOFETCH = "search-for-shadows-nofetch"; private static final File SEARCH_FOR_RESOURCES_FILE = new File(TEST_DIR, "search-for-resources.xml"); private static final File SEARCH_FOR_ROLES_FILE = new File(TEST_DIR, "search-for-roles.xml"); private static final File SEARCH_FOR_USERS_ACCOUNTS_FILE = new File(TEST_DIR, "search-for-users-accounts.xml"); private static final File SEARCH_FOR_USERS_ACCOUNTS_NOFETCH_FILE = new File(TEST_DIR, "search-for-users-accounts-nofetch.xml"); - private static final File DISABLE_JACK_FILE = new File(TEST_DIR, "disable-jack.xml"); - private static final File ENABLE_JACK_FILE = new File(TEST_DIR, "enable-jack.xml"); - private static final File DELETE_AND_ADD_JACK_FILE = new File(TEST_DIR, "delete-and-add-jack.xml"); - private static final File MODIFY_JACK_FILE = new File(TEST_DIR, "modify-jack.xml"); - private static final File MODIFY_JACK_BACK_FILE = new File(TEST_DIR, "modify-jack-back.xml"); - private static final File MODIFY_JACK_PASSWORD_FILE = new File(TEST_DIR, "modify-jack-password.xml"); - private static final File MODIFY_JACK_PASSWORD_TASK_FILE = new File(TEST_DIR, "modify-jack-password-task.xml"); - private static final String MODIFY_JACK_PASSWORD_TASK_OID = "9de76345-0f02-48de-86bf-e7a887cb374a"; - private static final File RECOMPUTE_JACK_FILE = new File(TEST_DIR, "recompute-jack.xml"); - private static final File ASSIGN_TO_JACK_FILE = new File(TEST_DIR, "assign-to-jack.xml"); - private static final File ASSIGN_TO_JACK_DRY_AND_RAW_FILE = new File(TEST_DIR, "assign-to-jack-dry-and-raw.xml"); - private static final File ASSIGN_TO_JACK_2_FILE = new File(TEST_DIR, "assign-to-jack-2.xml"); - private static final File UNASSIGN_FROM_WILL_FILE = new File(TEST_DIR, "unassign-from-will.xml"); - private static final File UNASSIGN_FROM_WILL_2_FILE = new File(TEST_DIR, "unassign-from-will-2.xml"); - private static final File UNASSIGN_FROM_WILL_3_FILE = new File(TEST_DIR, "unassign-from-will-3.xml"); - private static final File ASSIGN_TO_WILL_FILE = new File(TEST_DIR, "assign-to-will.xml"); - private static final File ASSIGN_TO_WILL_2_FILE = new File(TEST_DIR, "assign-to-will-2.xml"); - private static final File PURGE_DUMMY_BLACK_SCHEMA_FILE = new File(TEST_DIR, "purge-dummy-black-schema.xml"); - private static final File TEST_DUMMY_RESOURCE_FILE = new File(TEST_DIR, "test-dummy-resource.xml"); - private static final File NOTIFICATION_ABOUT_JACK_FILE = new File(TEST_DIR, "notification-about-jack.xml"); - private static final File NOTIFICATION_ABOUT_JACK_TYPE2_FILE = new File(TEST_DIR, "notification-about-jack-type2.xml"); - private static final File SCRIPTING_USERS_FILE = new File(TEST_DIR, "scripting-users.xml"); - private static final File SCRIPTING_USERS_IN_BACKGROUND_FILE = new File(TEST_DIR, "scripting-users-in-background.xml"); - private static final File SCRIPTING_USERS_IN_BACKGROUND_ASSIGN_FILE = new File(TEST_DIR, "scripting-users-in-background-assign.xml"); + private static final File SEARCH_FOR_USERS_RESOLVE_NAMES_FOR_ROLE_MEMBERSHIP_REF_FILE = new File(TEST_DIR, "search-for-users-resolve-names-for-roleMembershipRef.xml"); + private static final File SEARCH_FOR_USERS_RESOLVE_ROLE_MEMBERSHIP_REF_FILE = new File(TEST_DIR, "search-for-users-resolve-roleMembershipRef.xml"); + + // Tests 300-359 + private static final String DISABLE_JACK = "disable-jack"; + private static final String ENABLE_JACK = "enable-jack"; + private static final String DELETE_AND_ADD_JACK = "delete-and-add-jack"; + private static final String MODIFY_JACK = "modify-jack"; + private static final String MODIFY_JACK_BACK = "modify-jack-back"; + private static final String RECOMPUTE_JACK = "recompute-jack"; + + // Tests 360-399 + private static final String ASSIGN_CAPTAIN_AND_DUMMY_RED_TO_JACK = "assign-captain-and-dummy-red-to-jack"; + private static final String ASSIGN_TO_JACK_DRY_AND_RAW = "assign-to-jack-dry-and-raw"; + private static final String ASSIGN_NICE_PIRATE_BY_NAME_TO_JACK = "assign-nice-pirate-by-name-to-jack"; + + private static final String ASSIGN_PIRATE_MANAGER_TO_WILL = "assign-pirate-manager-to-will"; + private static final String UNASSIGN_PIRATE_DEFAULT_FROM_WILL = "unassign-pirate-default-from-will"; + private static final String UNASSIGN_PIRATE_MANAGER_AND_OWNER_FROM_WILL = "unassign-pirate-manager-and-owner-from-will"; + private static final String UNASSIGN_DUMMY_RESOURCE_FROM_WILL = "unassign-dummy-resource-from-will"; + private static final String ASSIGN_PIRATE_RELATION_CAPTAIN_TO_WILL = "assign-pirate-relation-captain-to-will"; + + // Tests 4xx + private static final String PURGE_DUMMY_BLACK_SCHEMA = "purge-dummy-black-schema"; + + private static final String TEST_DUMMY_RESOURCE = "test-dummy-resource"; + private static final String NOTIFICATION_ABOUT_JACK = "notification-about-jack"; + private static final String NOTIFICATION_ABOUT_JACK_TYPE2 = "notification-about-jack-type2"; + + // Tests 5xx + private static final String SCRIPTING_USERS = "scripting-users"; + private static final String SCRIPTING_USERS_IN_BACKGROUND = "scripting-users-in-background"; + private static final String SCRIPTING_USERS_IN_BACKGROUND_ASSIGN = "scripting-users-in-background-assign"; + + private static final String GENERATE_PASSWORDS = "generate-passwords"; + private static final String GENERATE_PASSWORDS_2 = "generate-passwords-2"; + private static final String GENERATE_PASSWORDS_3 = "generate-passwords-3"; + + private static final String USE_VARIABLES = "use-variables"; + private static final String START_TASKS_FROM_TEMPLATE = "start-tasks-from-template"; private static final File SCRIPTING_USERS_IN_BACKGROUND_TASK_FILE = new File(TEST_DIR, "scripting-users-in-background-task.xml"); - private static final File SCRIPTING_USERS_IN_BACKGROUND_ITERATIVE_TASK_FILE = new File(TEST_DIR, "scripting-users-in-background-iterative-task.xml"); - private static final File START_TASKS_FROM_TEMPLATE_FILE = new File(TEST_DIR, "start-tasks-from-template.xml"); - private static final File GENERATE_PASSWORDS_FILE = new File(TEST_DIR, "generate-passwords.xml"); - private static final File GENERATE_PASSWORDS_2_FILE = new File(TEST_DIR, "generate-passwords-2.xml"); - private static final File GENERATE_PASSWORDS_3_FILE = new File(TEST_DIR, "generate-passwords-3.xml"); - private static final File ECHO_FILE = new File(TEST_DIR, "echo.xml"); - private static final File USE_VARIABLES_FILE = new File(TEST_DIR, "use-variables.xml"); + + private static final String SCRIPTING_USERS_IN_BACKGROUND_ITERATIVE_TASK = "scripting-users-in-background-iterative-task"; + private static final File TASK_TO_RESUME_FILE = new File(TEST_DIR, "task-to-resume.xml"); private static final File TASK_TO_KEEP_SUSPENDED_FILE = new File(TEST_DIR, "task-to-keep-suspended.xml"); - private static final File RESUME_SUSPENDED_TASKS_FILE = new File(TEST_DIR, "resume-suspended-tasks.xml"); - private static final ItemName USER_NAME_TASK_EXTENSION_PROPERTY = new ItemName("http://midpoint.evolveum.com/xml/ns/samples/piracy", "userName"); - private static final ItemName USER_DESCRIPTION_TASK_EXTENSION_PROPERTY = new ItemName("http://midpoint.evolveum.com/xml/ns/samples/piracy", "userDescription"); - private static final ItemName STUDY_GROUP_TASK_EXTENSION_PROPERTY = new ItemName("http://midpoint.evolveum.com/xml/ns/samples/piracy", "studyGroup"); + private static final String RESUME_SUSPENDED_TASKS = "resume-suspended-tasks"; + + // Tests 6xx + private static final String MODIFY_JACK_PASSWORD = "modify-jack-password"; + private static final String MODIFY_JACK_PASSWORD_TASK = "modify-jack-password-task"; + private static final String MODIFY_JACK_PASSWORD_TASK_OID = "9de76345-0f02-48de-86bf-e7a887cb374a"; private static final String PASSWORD_PLAINTEXT_FRAGMENT = "pass1234wor"; private static final String PASSWORD_PLAINTEXT_1 = "pass1234wor1"; private static final String PASSWORD_PLAINTEXT_2 = "pass1234wor2"; private static final String PASSWORD_PLAINTEXT_3 = "pass1234wor3"; - @Autowired - private ScriptingExpressionEvaluator scriptingExpressionEvaluator; + @Autowired ScriptingExpressionEvaluator evaluator; @Override public void initSystem(Task initTask, OperationResult initResult) @@ -132,9 +155,6 @@ public void initSystem(Task initTask, OperationResult initResult) super.initSystem(initTask, initResult); InternalMonitor.reset(); -// InternalMonitor.setTraceShadowFetchOperation(true); -// InternalMonitor.setTraceResourceSchemaOperations(true); - DebugUtil.setPrettyPrintBeansAs(PrismContext.LANG_YAML); } @@ -143,53 +163,62 @@ protected File getSystemConfigurationFile() { return SYSTEM_CONFIGURATION_FILE; } + private File getFile(String name) { + return new File(TEST_DIR, name + getSuffix() + ".xml"); + } + + abstract String getSuffix(); + @Test public void test100EmptySequence() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); + ExpressionSequenceType sequence = new ExpressionSequenceType(); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(sequence, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(sequence, task, result); - // THEN + then(); dumpOutput(output, result); assertNoOutputData(output); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); } @Test public void test110EmptyPipeline() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); + ExpressionPipelineType pipeline = new ExpressionPipelineType(); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(pipeline, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(pipeline, task, result); - // THEN + then(); dumpOutput(output, result); assertNoOutputData(output); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); } @Test public void test112Echo() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ExecuteScriptType executeScript = parseExecuteScript(ECHO_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(executeScript, VariablesMap.emptyMap(), false, task, result); + ExecuteScriptType executeScript = parseExecuteScript(ECHO); + + when(); + ExecutionContext output = evaluator.evaluateExpression(executeScript, VariablesMap.emptyMap(), false, task, result); - // THEN + then(); dumpOutput(output, result); - result.computeStatus(); + PipelineData data = output.getFinalOutput(); assertEquals("Unexpected # of items in output", 4, data.getData().size()); @@ -198,70 +227,66 @@ public void test112Echo() throws Exception { @Test public void test120Log() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType logAction = parseScriptingExpression(LOG_FILE); + + ScriptingExpressionType logAction = parseScriptingExpression(LOG); LogfileTestTailer tailer = new LogfileTestTailer(LoggingConfigurationManager.AUDIT_LOGGER_NAME); tailer.tail(); tailer.setExpecteMessage("Custom message:"); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(logAction, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(logAction, task, result); - // THEN + then(); dumpOutput(output, result); assertNoOutputData(output); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); tailer.tail(); tailer.assertExpectedMessage(); } - private ScriptingExpressionType parseScriptingExpression(File file) throws IOException, SchemaException { - // we cannot specify explicit type parameter here, as the parsed files contain subtypes of ScriptingExpressionType - return prismContext.parserFor(file).parseRealValue(); - } - - private ExecuteScriptType parseExecuteScript(File file) throws IOException, SchemaException { - return prismContext.parserFor(file).parseRealValue(ExecuteScriptType.class); - } - @Test public void test200SearchUser() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); + + // no legacy/new versions here ScriptingExpressionType expression = parseScriptingExpression(SEARCH_FOR_USERS_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); assertEquals(2, output.getFinalOutput().getData().size()); } @Test public void test202SearchUserWithExpressions() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); + + // no legacy/new versions here ExecuteScriptType executeScript = prismContext.parserFor(SEARCH_FOR_USERS_WITH_EXPRESSIONS_FILE).parseRealValue(); VariablesMap variables = new VariablesMap(); variables.put("value1", "administrator", String.class); variables.put("value2", "jack", String.class); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(executeScript, variables, false, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(executeScript, variables, false, task, result); - // THEN + then(); dumpOutput(output, result); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); assertEquals(2, output.getFinalOutput().getData().size()); assertEquals(new HashSet<>(Arrays.asList("administrator", "jack")), output.getFinalOutput().getData().stream() @@ -271,242 +296,330 @@ public void test202SearchUserWithExpressions() throws Exception { @Test public void test205SearchForResources() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); + + // no legacy/new versions here ScriptingExpressionType expression = parseScriptingExpression(SEARCH_FOR_RESOURCES_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); assertEquals(13, output.getFinalOutput().getData().size()); } @Test public void test206SearchForRoles() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); + + // no legacy/new versions here ScriptingExpressionType expression = parseScriptingExpression(SEARCH_FOR_ROLES_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); } @Test public void test210SearchForShadows() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); + + // no legacy/new versions here ScriptingExpressionType expression = parseScriptingExpression(SEARCH_FOR_SHADOWS_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); assertEquals(5, output.getFinalOutput().getData().size()); assertAttributesFetched(output.getFinalOutput().getData()); } @Test public void test215SearchForShadowsNoFetch() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(SEARCH_FOR_SHADOWS_NOFETCH_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + ScriptingExpressionType expression = parseScriptingExpression(SEARCH_FOR_SHADOWS_NOFETCH); + + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); assertEquals(5, output.getFinalOutput().getData().size()); assertAttributesNotFetched(output.getFinalOutput().getData()); } @Test public void test220SearchForUsersAccounts() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); ScriptingExpressionType expression = parseScriptingExpression(SEARCH_FOR_USERS_ACCOUNTS_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); assertEquals(4, output.getFinalOutput().getData().size()); assertAttributesFetched(output.getFinalOutput().getData()); } @Test public void test225SearchForUsersAccountsNoFetch() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); ScriptingExpressionType expression = parseScriptingExpression(SEARCH_FOR_USERS_ACCOUNTS_NOFETCH_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); assertEquals(4, output.getFinalOutput().getData().size()); assertAttributesNotFetched(output.getFinalOutput().getData()); } + @Test + public void test230SearchUserResolveNamesForRoleMembershipRef() throws Exception { + given(); + Task task = getTestTask(); + OperationResult result = task.getResult(); + ScriptingExpressionType expression = parseScriptingExpression(SEARCH_FOR_USERS_RESOLVE_NAMES_FOR_ROLE_MEMBERSHIP_REF_FILE); + + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); + + then(); + dumpOutput(output, result); + + assertSuccess(result); + assertEquals(2, output.getFinalOutput().getData().size()); + //assertEquals("administrator", ((PrismObject) output.getData().get(0)).asObjectable().getName().getOrig()); + + for (PipelineItem item : output.getFinalOutput().getData()) { + PrismAsserts.assertHasTargetName((PrismContainerValue) item.getValue(), UserType.F_ROLE_MEMBERSHIP_REF); + PrismAsserts.assertHasNoTargetName((PrismContainerValue) item.getValue(), UserType.F_LINK_REF); + } + } + + @Test + public void test240SearchUserResolveRoleMembershipRef() throws Exception { + given(); + Task task = getTestTask(); + OperationResult result = task.getResult(); + ScriptingExpressionType expression = parseScriptingExpression(SEARCH_FOR_USERS_RESOLVE_ROLE_MEMBERSHIP_REF_FILE); + + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); + + then(); + dumpOutput(output, result); + + assertSuccess(result); + assertEquals(2, output.getFinalOutput().getData().size()); + + for (PipelineItem item : output.getFinalOutput().getData()) { + PrismAsserts.assertHasObject((PrismContainerValue) item.getValue(), UserType.F_ROLE_MEMBERSHIP_REF); + PrismAsserts.assertHasNoObject((PrismContainerValue) item.getValue(), UserType.F_LINK_REF); + } + } + @Test public void test300DisableJack() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(DISABLE_JACK_FILE); + ScriptingExpressionType expression = parseScriptingExpression(DISABLE_JACK); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); assertOutputData(output, 1, OperationResultStatus.SUCCESS); assertEquals("Disabled user:c0c010c0-d34d-b33f-f00d-111111111111(jack)\n", output.getConsoleOutput()); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); assertAdministrativeStatusDisabled(searchObjectByName(UserType.class, "jack")); } @Test public void test310EnableJack() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(ENABLE_JACK_FILE); + ScriptingExpressionType expression = parseScriptingExpression(ENABLE_JACK); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); assertOutputData(output, 1, OperationResultStatus.SUCCESS); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); assertEquals("Enabled user:c0c010c0-d34d-b33f-f00d-111111111111(jack)\n", output.getConsoleOutput()); assertAdministrativeStatusEnabled(searchObjectByName(UserType.class, "jack")); } @Test public void test320DeleteAndAddJack() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(DELETE_AND_ADD_JACK_FILE); + ScriptingExpressionType expression = parseScriptingExpression(DELETE_AND_ADD_JACK); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); assertOutputData(output, 1, OperationResultStatus.SUCCESS); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); assertEquals("Deleted user:c0c010c0-d34d-b33f-f00d-111111111111(jack)\nAdded user:c0c010c0-d34d-b33f-f00d-111111111111(jack)\n", output.getConsoleOutput()); assertAdministrativeStatusEnabled(searchObjectByName(UserType.class, "jack")); } @Test public void test330ModifyJack() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(MODIFY_JACK_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + ScriptingExpressionType expression = parseScriptingExpression(MODIFY_JACK); - // THEN + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); + + then(); dumpOutput(output, result); assertOutputData(output, 1, OperationResultStatus.SUCCESS); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); assertEquals("Modified user:c0c010c0-d34d-b33f-f00d-111111111111(jack)\n", output.getConsoleOutput()); - assertEquals("Nowhere", searchObjectByName(UserType.class, "jack").asObjectable().getLocality().getOrig()); + assertUserAfterByUsername(USER_JACK_USERNAME) + .assertLocality("Nowhere"); } @Test public void test340ModifyJackBack() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(MODIFY_JACK_BACK_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + ScriptingExpressionType expression = parseScriptingExpression(MODIFY_JACK_BACK); + + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); assertOutputData(output, 1, OperationResultStatus.SUCCESS); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); assertEquals("Modified user:c0c010c0-d34d-b33f-f00d-111111111111(jack)\n", output.getConsoleOutput()); - assertEquals("Caribbean", searchObjectByName(UserType.class, "jack").asObjectable().getLocality().getOrig()); + assertUserAfterByUsername(USER_JACK_USERNAME) + .assertLocality("Caribbean"); } @Test public void test350RecomputeJack() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(RECOMPUTE_JACK_FILE); + ScriptingExpressionType expression = parseScriptingExpression(RECOMPUTE_JACK); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); assertOutputData(output, 1, OperationResultStatus.SUCCESS); - result.computeStatus(); - TestUtil.assertSuccess(result); + assertSuccess(result); assertEquals("Recomputed user:c0c010c0-d34d-b33f-f00d-111111111111(jack)\n", output.getConsoleOutput()); } @Test - public void test360AssignToJack() throws Exception { - // GIVEN + public void test352RecomputeJackTriggerDirect() throws Exception { + throw new SkipException("Only in new scripting tests"); + } + + @Test + public void test353RecomputeJackTriggerOptimized() throws Exception { + throw new SkipException("Only in new scripting tests"); + } + + @Test + public void test360AssignCaptainAndDummyRedToJack() throws Exception { + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(ASSIGN_TO_JACK_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + ScriptingExpressionType expression = parseScriptingExpression(ASSIGN_CAPTAIN_AND_DUMMY_RED_TO_JACK); + + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); assertOutputData(output, 1, OperationResultStatus.SUCCESS); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); //assertEquals("Recomputed user:c0c010c0-d34d-b33f-f00d-111111111111(jack)\n", output.getConsoleOutput()); - PrismObject jack = getUser(USER_JACK_OID); - display("jack after assignments creation", jack); - assertAssignedAccount(jack, "10000000-0000-0000-0000-000000000104"); - assertAssignedRole(jack, "12345678-d34d-b33f-f00d-55555555cccc"); + assertUserAfterByUsername(USER_JACK_USERNAME) + .assignments() + .assertAssignments(2) + .by() + .targetOid(ROLE_CAPTAIN_OID) + .find() + .end() + .by() + .resourceOid(RESOURCE_DUMMY_RED_OID) + .find() + .end(); + } + + @Test + public void test361UnassignCaptainFromJack() throws Exception { + throw new SkipException("Only in new scripting tests"); + } + + @Test + public void test363AssignCaptainByNameToJack() throws Exception { + throw new SkipException("Only in new scripting tests"); + } + + @Test + public void test364UnassignAllFromJack() throws Exception { + throw new SkipException("Only in new scripting tests"); } /** @@ -517,11 +630,12 @@ public void test365AssignToJackDryAndRaw() throws Exception { given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(ASSIGN_TO_JACK_DRY_AND_RAW_FILE); + + ScriptingExpressionType expression = parseScriptingExpression(ASSIGN_TO_JACK_DRY_AND_RAW); when(); try { - scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + evaluator.evaluateExpression(expression, task, result); fail("unexpected success"); } catch (ScriptExecutionException e) { displayExpectedException(e); @@ -530,190 +644,248 @@ public void test365AssignToJackDryAndRaw() throws Exception { } @Test - public void test370AssignToJackInBackground() throws Exception { - // GIVEN + public void test370AssignNicePirateByNameToJackInBackground() throws Exception { + given(); OperationResult result = getTestOperationResult(); - ScriptingExpressionType expression = parseScriptingExpression(ASSIGN_TO_JACK_2_FILE); - // WHEN + ScriptingExpressionType expression = parseScriptingExpression(ASSIGN_NICE_PIRATE_BY_NAME_TO_JACK); + + when(); Task task = taskManager.createTaskInstance(); task.setOwner(getUser(USER_ADMINISTRATOR_OID)); - scriptingExpressionEvaluator.evaluateExpressionInBackground(expression, task, result); + evaluator.evaluateExpressionInBackground(expression, task, result); waitForTaskFinish(task.getOid(), false); task.refresh(result); - // THEN - display(task.getResult()); - TestUtil.assertSuccess(task.getResult()); - PrismObject jack = getUser(USER_JACK_OID); - display("jack after assignment creation", jack); - assertAssignedRole(jack, "12345678-d34d-b33f-f00d-555555556677"); + then(); + assertSuccess(task.getResult()); + assertUserAfterByUsername(USER_JACK_USERNAME) + .assignments() + .assertRole(ROLE_NICE_PIRATE_OID); } @Test - public void test390AssignToWill() throws Exception { - // GIVEN + public void test390AssignToWillRolePirateManager() throws Exception { + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(ASSIGN_TO_WILL_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + assertUserBefore(USER_WILL_OID) + .assignments() + .assertAssignments(3); + + ScriptingExpressionType expression = parseScriptingExpression(ASSIGN_PIRATE_MANAGER_TO_WILL); - // THEN + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); + + then(); dumpOutput(output, result); assertOutputData(output, 1, OperationResultStatus.SUCCESS); - result.computeStatus(); - TestUtil.assertSuccess(result); - PrismObject will = getUser(USER_WILL_OID); - display("will after assignments creation", will); - MidPointAsserts.assertAssigned(will, "12345678-d34d-b33f-f00d-555555556666", RoleType.COMPLEX_TYPE, RelationTypes.MANAGER.getRelation()); + + assertSuccess(result); + assertUserAfter(USER_WILL_OID) + .assignments() + .assertAssignments(4) + .by() + .targetOid(ROLE_PIRATE_OID) + .targetRelation(SchemaConstants.ORG_MANAGER) + .find(); } @Test - public void test391UnassignFromWill() throws Exception { - // GIVEN + public void test391UnassignPirateDefaultFromWill() throws Exception { + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(UNASSIGN_FROM_WILL_FILE); + ScriptingExpressionType expression = parseScriptingExpression(UNASSIGN_PIRATE_DEFAULT_FROM_WILL); + + assertUserBefore(USER_WILL_OID) + .assignments() + .assertAssignments(4) + .by() + .targetOid(ROLE_PIRATE_OID) + .targetRelation(SchemaConstants.ORG_MANAGER) + .find() + .end() + .by() + .targetOid(ROLE_PIRATE_OID) + .targetRelation(SchemaConstants.ORG_DEFAULT) + .find() + .end() + .by() + .targetOid(ROLE_PIRATE_OID) + .targetRelation(SchemaConstants.ORG_OWNER) + .find() + .end() + .by() + .resourceOid(RESOURCE_DUMMY_OID) + .find(); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); assertOutputData(output, 1, OperationResultStatus.SUCCESS); - result.computeStatus(); - TestUtil.assertSuccess(result); - PrismObject will = getUser(USER_WILL_OID); - display("will after unassign assignment", will); - MidPointAsserts.assertNotAssigned(will, "12345678-d34d-b33f-f00d-555555556666", RoleType.COMPLEX_TYPE, RelationTypes.MEMBER.getRelation()); - MidPointAsserts.assertAssigned(will, "12345678-d34d-b33f-f00d-555555556666", RoleType.COMPLEX_TYPE, RelationTypes.MANAGER.getRelation()); - MidPointAsserts.assertAssignedResource(will, "10000000-0000-0000-0000-000000000004"); + + assertSuccess(result); + assertUserAfter(USER_WILL_OID) + .assignments() + .assertAssignments(3) + .by() + .targetOid(ROLE_PIRATE_OID) + .targetRelation(SchemaConstants.ORG_MANAGER) + .find() + .end() + .by() + .targetOid(ROLE_PIRATE_OID) + .targetRelation(SchemaConstants.ORG_OWNER) + .find() + .end() + .by() + .resourceOid(RESOURCE_DUMMY_OID) + .find(); } @Test - public void test392UnassignFromWill2() throws Exception { - // GIVEN + public void test392UnassignPirateManagerAndOwnerFromWill() throws Exception { + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(UNASSIGN_FROM_WILL_2_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + ScriptingExpressionType expression = parseScriptingExpression(UNASSIGN_PIRATE_MANAGER_AND_OWNER_FROM_WILL); + + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); assertOutputData(output, 1, OperationResultStatus.SUCCESS); - result.computeStatus(); - TestUtil.assertSuccess(result); - PrismObject will = getUser(USER_WILL_OID); - display("will after unassign assignment", will); - MidPointAsserts.assertNotAssigned(will, "12345678-d34d-b33f-f00d-555555556666", RoleType.COMPLEX_TYPE, RelationTypes.MANAGER.getRelation()); - MidPointAsserts.assertNotAssigned(will, "12345678-d34d-b33f-f00d-555555556666", RoleType.COMPLEX_TYPE, RelationTypes.OWNER.getRelation()); - MidPointAsserts.assertAssignedResource(will, "10000000-0000-0000-0000-000000000004"); + + assertSuccess(result); + assertUserAfter(USER_WILL_OID) + .assignments() + .assertAssignments(1) + .by() + .resourceOid(RESOURCE_DUMMY_OID) + .find(); } @Test - public void test393UnassignFromWill3() throws Exception { - // GIVEN + public void test393UnassignDummyResourceFromWill() throws Exception { + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(UNASSIGN_FROM_WILL_3_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + ScriptingExpressionType expression = parseScriptingExpression(UNASSIGN_DUMMY_RESOURCE_FROM_WILL); - // THEN + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); + + then(); dumpOutput(output, result); assertOutputData(output, 1, OperationResultStatus.SUCCESS); - result.computeStatus(); - TestUtil.assertSuccess(result); - PrismObject will = getUser(USER_WILL_OID); - display("will after unassign assignment", will); - MidPointAsserts.assertNotAssigned(will, "12345678-d34d-b33f-f00d-555555556666", RoleType.COMPLEX_TYPE, RelationTypes.MEMBER.getRelation()); - MidPointAsserts.assertNotAssigned(will, "12345678-d34d-b33f-f00d-555555556666", RoleType.COMPLEX_TYPE, RelationTypes.MANAGER.getRelation()); - MidPointAsserts.assertNotAssignedResource(will, "10000000-0000-0000-0000-000000000004"); + + assertSuccess(result); + assertUserAfter(USER_WILL_OID) + .assignments() + .assertAssignments(0); } @Test - public void test394AssignToWill2() throws Exception { - // GIVEN + public void test394AssignPirateRelationCaptainToWill() throws Exception { + given(); QName customRelation = new QName("http://midpoint.evolveum.com/xml/ns/samples/piracy", "captain"); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(ASSIGN_TO_WILL_2_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + ScriptingExpressionType expression = parseScriptingExpression(ASSIGN_PIRATE_RELATION_CAPTAIN_TO_WILL); - // THEN + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); + + then(); dumpOutput(output, result); assertOutputData(output, 1, OperationResultStatus.SUCCESS); - result.computeStatus(); - TestUtil.assertSuccess(result); - PrismObject will = getUser(USER_WILL_OID); - display("will after assignments creation", will); - MidPointAsserts.assertAssigned(will, "12345678-d34d-b33f-f00d-555555556666", RoleType.COMPLEX_TYPE, customRelation); + + assertSuccess(result); + assertUserAfter(USER_WILL_OID) + .assignments() + .assertAssignments(1) + .by() + .targetOid(ROLE_PIRATE_OID) + .targetRelation(customRelation) + .find(); } @Test public void test400PurgeSchema() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(PURGE_DUMMY_BLACK_SCHEMA_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + ScriptingExpressionType expression = parseScriptingExpression(PURGE_DUMMY_BLACK_SCHEMA); + + assertResourceBefore(RESOURCE_DUMMY_BLACK_OID) + .assertHasSchema(); - // THEN + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); + + then(); dumpOutput(output, result); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); assertEquals(1, output.getFinalOutput().getData().size()); - //AssertJUnit.assertNull("Schema is still present", dummy.getSchema()); - // actually, schema gets downloaded just after purging it assertEquals("Purged schema information from resource:10000000-0000-0000-0000-000000000305(Dummy Resource Black)\n", output.getConsoleOutput()); + + PrismObject resourceAfter = modelService.getObject(ResourceType.class, + RESOURCE_DUMMY_BLACK_OID, getOperationOptionsBuilder().noFetch().build(), task, result); + assertResource(resourceAfter, "after (no fetch)") + .display() + .assertHasNoSchema(); } @Test public void test410TestResource() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(TEST_DUMMY_RESOURCE_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + ScriptingExpressionType expression = parseScriptingExpression(TEST_DUMMY_RESOURCE); + + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); ResourceType dummy = modelService.getObject(ResourceType.class, RESOURCE_DUMMY_OID, null, taskManager.createTaskInstance(), result).asObjectable(); display("dummy resource after test connection", dummy.asPrismObject()); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); assertEquals(1, output.getFinalOutput().getData().size()); assertEquals("Tested resource:10000000-0000-0000-0000-000000000004(Dummy Resource): SUCCESS\n", output.getConsoleOutput()); } @Test public void test420NotificationAboutJack() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(NOTIFICATION_ABOUT_JACK_FILE); + + ScriptingExpressionType expression = parseScriptingExpression(NOTIFICATION_ABOUT_JACK); prepareNotifications(); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); assertOutputData(output, 1, OperationResultStatus.SUCCESS); assertEquals("Produced 1 event(s)\n", output.getConsoleOutput()); @@ -726,19 +898,20 @@ public void test420NotificationAboutJack() throws Exception { @Test public void test430NotificationAboutJackType2() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(NOTIFICATION_ABOUT_JACK_TYPE2_FILE); + + ScriptingExpressionType expression = parseScriptingExpression(NOTIFICATION_ABOUT_JACK_TYPE2); prepareNotifications(); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); assertOutputData(output, 1, OperationResultStatus.SUCCESS); assertEquals("Produced 1 event(s)\n", output.getConsoleOutput()); @@ -756,18 +929,19 @@ public void test430NotificationAboutJackType2() throws Exception { @Test public void test500ScriptingUsers() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(SCRIPTING_USERS_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + ScriptingExpressionType expression = parseScriptingExpression(SCRIPTING_USERS); - // THEN + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); + + then(); dumpOutput(output, result); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); PipelineData data = output.getFinalOutput(); assertEquals("Unexpected # of items in output", 6, data.getData().size()); Set realOids = new HashSet<>(); @@ -786,13 +960,14 @@ public void test500ScriptingUsers() throws Exception { @Test public void test505ScriptingUsersInBackground() throws Exception { - // GIVEN + given(); Task task = getTestTask(); task.setOwner(getUser(USER_ADMINISTRATOR_OID)); OperationResult result = task.getResult(); - ExecuteScriptType exec = prismContext.parserFor(SCRIPTING_USERS_IN_BACKGROUND_FILE).parseRealValue(); - // WHEN + ExecuteScriptType exec = parseExecuteScript(SCRIPTING_USERS_IN_BACKGROUND); + + when(); task.setExtensionPropertyValue(SchemaConstants.SE_EXECUTE_SCRIPT, exec); task.getExtensionOrClone() @@ -812,7 +987,7 @@ public void test505ScriptingUsersInBackground() throws Exception { waitForTaskFinish(task.getOid(), false); task.refresh(result); - // THEN + then(); display(task.getResult()); TestUtil.assertSuccess(task.getResult()); PrismObject admin = getUser(USER_ADMINISTRATOR_OID); @@ -828,13 +1003,14 @@ public void test505ScriptingUsersInBackground() throws Exception { @Test public void test507ScriptingUsersInBackgroundAssign() throws Exception { - // GIVEN + given(); Task task = getTestTask(); task.setOwner(getUser(USER_ADMINISTRATOR_OID)); OperationResult result = task.getResult(); - ExecuteScriptType exec = prismContext.parserFor(SCRIPTING_USERS_IN_BACKGROUND_ASSIGN_FILE).parseRealValue(); - // WHEN + ExecuteScriptType exec = parseExecuteScript(SCRIPTING_USERS_IN_BACKGROUND_ASSIGN); + + when(); task.setExtensionPropertyValue(SchemaConstants.SE_EXECUTE_SCRIPT, exec); task.setHandlerUri(ModelPublicConstants.SCRIPT_EXECUTION_TASK_HANDLER_URI); @@ -848,7 +1024,7 @@ public void test507ScriptingUsersInBackgroundAssign() throws Exception { waitForTaskFinish(task.getOid(), false); task.refresh(result); - // THEN + then(); display(task.getResult()); TestUtil.assertSuccess(task.getResult()); PrismObject admin = getUser(USER_ADMINISTRATOR_OID); @@ -864,10 +1040,11 @@ public void test507ScriptingUsersInBackgroundAssign() throws Exception { @Test public void test510GeneratePasswords() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(GENERATE_PASSWORDS_FILE); + + ScriptingExpressionType expression = parseScriptingExpression(GENERATE_PASSWORDS); addObject(PASSWORD_POLICY_GLOBAL_FILE); @@ -878,13 +1055,13 @@ public void test510GeneratePasswords() throws Exception { .asItemDeltas(); modifySystemObjectInRepo(SecurityPolicyType.class, SECURITY_POLICY_OID, itemDeltas, result); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); - // THEN + then(); dumpOutput(output, result); - result.computeStatus(); - TestUtil.assertSuccess(result); + + assertSuccess(result); PipelineData data = output.getFinalOutput(); assertEquals("Unexpected # of items in output", 6, data.getData().size()); Set realOids = new HashSet<>(); @@ -903,18 +1080,19 @@ public void test510GeneratePasswords() throws Exception { @Test public void test520GeneratePasswordsFullInput() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ExecuteScriptType executeScript = parseExecuteScript(GENERATE_PASSWORDS_2_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(executeScript, VariablesMap.emptyMap(), false, task, result); + ExecuteScriptType executeScript = parseExecuteScript(GENERATE_PASSWORDS_2); + + when(); + ExecutionContext output = evaluator.evaluateExpression(executeScript, VariablesMap.emptyMap(), false, task, result); - // THEN + then(); dumpOutput(output, result); - result.computeStatus(); - //TestUtil.assertSuccess(result); + + //assertSuccess(result); PipelineData data = output.getFinalOutput(); List items = data.getData(); assertEquals("Unexpected # of items in output", 4, items.size()); @@ -926,17 +1104,18 @@ public void test520GeneratePasswordsFullInput() throws Exception { @Test public void test530GeneratePasswordsReally() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ExecuteScriptType executeScript = parseExecuteScript(GENERATE_PASSWORDS_3_FILE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(executeScript, VariablesMap.emptyMap(), false, task, result); + ExecuteScriptType executeScript = parseExecuteScript(GENERATE_PASSWORDS_3); - // THEN + when(); + ExecutionContext output = evaluator.evaluateExpression(executeScript, VariablesMap.emptyMap(), false, task, result); + + then(); dumpOutput(output, result); - result.computeStatus(); + PipelineData data = output.getFinalOutput(); List items = data.getData(); assertEquals("Unexpected # of items in output", 3, items.size()); @@ -963,57 +1142,12 @@ private void checkPassword(PipelineItem item, String userOid) assertEquals("Wrong password stored in repository", returnedClearValue, repoClearValue); } - @Test - public void test540SearchUserResolveNamesForRoleMembershipRef() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(SEARCH_FOR_USERS_RESOLVE_NAMES_FOR_ROLE_MEMBERSHIP_REF_FILE); - - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); - - // THEN - dumpOutput(output, result); - result.computeStatus(); - TestUtil.assertSuccess(result); - assertEquals(2, output.getFinalOutput().getData().size()); - //assertEquals("administrator", ((PrismObject) output.getData().get(0)).asObjectable().getName().getOrig()); - - for (PipelineItem item : output.getFinalOutput().getData()) { - PrismAsserts.assertHasTargetName((PrismContainerValue) item.getValue(), UserType.F_ROLE_MEMBERSHIP_REF); - PrismAsserts.assertHasNoTargetName((PrismContainerValue) item.getValue(), UserType.F_LINK_REF); - } - } - - @Test - public void test545SearchUserResolveRoleMembershipRef() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - ScriptingExpressionType expression = parseScriptingExpression(SEARCH_FOR_USERS_RESOLVE_ROLE_MEMBERSHIP_REF_FILE); - - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(expression, task, result); - - // THEN - dumpOutput(output, result); - result.computeStatus(); - TestUtil.assertSuccess(result); - assertEquals(2, output.getFinalOutput().getData().size()); - - for (PipelineItem item : output.getFinalOutput().getData()) { - PrismAsserts.assertHasObject((PrismContainerValue) item.getValue(), UserType.F_ROLE_MEMBERSHIP_REF); - PrismAsserts.assertHasNoObject((PrismContainerValue) item.getValue(), UserType.F_LINK_REF); - } - } - @Test public void test550UseVariables() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - ExecuteScriptType executeScript = parseExecuteScript(USE_VARIABLES_FILE); + ExecuteScriptType executeScript = parseExecuteScript(USE_VARIABLES); PrismContainer taskExtension = task.getOrCreateExtension(); taskExtension @@ -1023,12 +1157,12 @@ public void test550UseVariables() throws Exception { .findOrCreateProperty(STUDY_GROUP_TASK_EXTENSION_PROPERTY) .addRealValues("group1", "group2", "group3"); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(executeScript, VariablesMap.emptyMap(), false, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(executeScript, VariablesMap.emptyMap(), false, task, result); - // THEN + then(); dumpOutput(output, result); - result.computeStatus(); + PipelineData data = output.getFinalOutput(); assertEquals("Unexpected # of items in output", 1, data.getData().size()); @@ -1038,19 +1172,20 @@ public void test550UseVariables() throws Exception { @Test public void test560StartTaskFromTemplate() throws Exception { - // GIVEN + given(); Task task = getTestTask(); task.setOwner(getUser(USER_ADMINISTRATOR_OID)); OperationResult result = task.getResult(); + repoAddObjectFromFile(SCRIPTING_USERS_IN_BACKGROUND_TASK_FILE, result); - ExecuteScriptType exec = prismContext.parserFor(START_TASKS_FROM_TEMPLATE_FILE).parseRealValue(); + ExecuteScriptType exec = parseExecuteScript(START_TASKS_FROM_TEMPLATE); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(exec, VariablesMap.emptyMap(), false, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(exec, VariablesMap.emptyMap(), false, task, result); - // THEN + then(); dumpOutput(output, result); - result.computeStatus(); + PipelineData data = output.getFinalOutput(); assertEquals("Unexpected # of items in output", 2, data.getData().size()); @@ -1084,15 +1219,16 @@ public void test560StartTaskFromTemplate() throws Exception { @Test public void test570IterativeScriptingTask() throws Exception { - // GIVEN + given(); Task task = getTestTask(); OperationResult result = task.getResult(); - String taskOid = repoAddObjectFromFile(SCRIPTING_USERS_IN_BACKGROUND_ITERATIVE_TASK_FILE, result).getOid(); - // WHEN + String taskOid = repoAddObjectFromFile(getFile(SCRIPTING_USERS_IN_BACKGROUND_ITERATIVE_TASK), result).getOid(); + + when(); waitForTaskFinish(taskOid, false); - // THEN + then(); PrismObject jack = getUser(USER_JACK_OID); PrismObject administrator = getUser(USER_ADMINISTRATOR_OID); display("jack", jack); @@ -1101,54 +1237,52 @@ public void test570IterativeScriptingTask() throws Exception { assertEquals("Wrong administrator description", "hello administrator", administrator.asObjectable().getDescription()); } - @Test(enabled = false) // probably obsolete + @Test public void test575ResumeTask() throws Exception { - // GIVEN + given(); Task task = getTestTask(); task.setOwner(getUser(USER_ADMINISTRATOR_OID)); OperationResult result = task.getResult(); + String taskToResumeOid = addObject(TASK_TO_RESUME_FILE); addObject(TASK_TO_KEEP_SUSPENDED_FILE); - PrismObject taskToResume = prismContext.parseObject(TASK_TO_RESUME_FILE); - //TODO deal with this - //taskToResume.asObjectable().getApprovalContext().setEndTimestamp(fromNow(createDuration(-1000L))); - addObject(taskToResume); - display("task to resume", taskToResume); - - ExecuteScriptType exec = prismContext.parserFor(RESUME_SUSPENDED_TASKS_FILE).parseRealValue(); + ExecuteScriptType exec = parseExecuteScript(RESUME_SUSPENDED_TASKS); - // WHEN - ExecutionContext output = scriptingExpressionEvaluator.evaluateExpression(exec, VariablesMap.emptyMap(), false, task, result); + when(); + ExecutionContext output = evaluator.evaluateExpression(exec, VariablesMap.emptyMap(), false, task, result); - // THEN + then(); dumpOutput(output, result); - result.computeStatus(); + // the task should be there assertEquals("Unexpected # of items in output", 1, output.getFinalOutput().getData().size()); - PrismObject taskAfter = getObject(TaskType.class, taskToResume.getOid()); + PrismObject taskAfter = getObject(TaskType.class, taskToResumeOid); assertNotSame("Task is still suspended", taskAfter.asObjectable().getExecutionStatus(), TaskExecutionStatusType.SUSPENDED); } - // MID-5359 + /** + * MID-5359 + */ @Test public void test600ModifyJackPasswordInBackground() throws Exception { - // GIVEN + given(); OperationResult result = getTestOperationResult(); - ScriptingExpressionType expression = parseScriptingExpression(MODIFY_JACK_PASSWORD_FILE); + + ScriptingExpressionType expression = parseScriptingExpression(MODIFY_JACK_PASSWORD); prepareNotifications(); dummyAuditService.clear(); - // WHEN + when(); Task task = taskManager.createTaskInstance(); task.setOwner(getUser(USER_ADMINISTRATOR_OID)); - scriptingExpressionEvaluator.evaluateExpressionInBackground(expression, task, result); + evaluator.evaluateExpressionInBackground(expression, task, result); waitForTaskFinish(task.getOid(), false); task.refresh(result); - // THEN + then(); display(task.getResult()); TestUtil.assertSuccess(task.getResult()); PrismObject jack = getUser(USER_JACK_OID); @@ -1163,10 +1297,12 @@ public void test600ModifyJackPasswordInBackground() throws Exception { displayDumpable("Audit", dummyAuditService); } - // MID-5359 + /** + * MID-5359 + */ @Test public void test610ModifyJackPasswordImportingTask() throws Exception { - // GIVEN + given(); Task opTask = getTestTask(); opTask.setOwner(getUser(USER_ADMINISTRATOR_OID)); OperationResult result = opTask.getResult(); @@ -1174,17 +1310,16 @@ public void test610ModifyJackPasswordImportingTask() throws Exception { prepareNotifications(); dummyAuditService.clear(); - // WHEN - FileInputStream stream = new FileInputStream(MODIFY_JACK_PASSWORD_TASK_FILE); + when(); + FileInputStream stream = new FileInputStream(getFile(MODIFY_JACK_PASSWORD_TASK)); modelService.importObjectsFromStream(stream, PrismContext.LANG_XML, null, opTask, result); stream.close(); - result.computeStatus(); assertSuccess(result); Task task = waitForTaskFinish(MODIFY_JACK_PASSWORD_TASK_OID, false); - // THEN + then(); display(task.getResult()); TestUtil.assertSuccess(task.getResult()); PrismObject jack = getUser(USER_JACK_OID); @@ -1199,10 +1334,12 @@ public void test610ModifyJackPasswordImportingTask() throws Exception { displayDumpable("Audit", dummyAuditService); } - // not using scripting as such, but related... MID-5359 + /** + * MID-5359 (not using scripting as such, but related) + */ @Test public void test620ModifyJackPasswordViaExecuteChangesAsynchronously() throws Exception { - // GIVEN + given(); Task opTask = getTestTask(); opTask.setOwner(getUser(USER_ADMINISTRATOR_OID)); OperationResult result = opTask.getResult(); @@ -1210,7 +1347,7 @@ public void test620ModifyJackPasswordViaExecuteChangesAsynchronously() throws Ex prepareNotifications(); dummyAuditService.clear(); - // WHEN + when(); ProtectedStringType password = new ProtectedStringType(); password.setClearValue(PASSWORD_PLAINTEXT_3); @@ -1220,12 +1357,11 @@ public void test620ModifyJackPasswordViaExecuteChangesAsynchronously() throws Ex .asObjectDelta(USER_JACK_OID); TaskType newTask = libraryMidpointFunctions.executeChangesAsynchronously(singleton(delta), null, null, opTask, result); - result.computeStatus(); assertSuccess(result); Task task = waitForTaskFinish(newTask.getOid(), false); - // THEN + then(); display(task.getResult()); TestUtil.assertSuccess(task.getResult()); PrismObject jack = getUser(USER_JACK_OID); @@ -1245,7 +1381,7 @@ private void assertNoOutputData(ExecutionContext output) { } @SuppressWarnings("SameParameterValue") - private void assertOutputData(ExecutionContext output, int size, OperationResultStatus status) { + void assertOutputData(ExecutionContext output, int size, OperationResultStatus status) { assertEquals("Wrong # of output items", size, output.getFinalOutput().getData().size()); for (PipelineItem item : output.getFinalOutput().getData()) { assertEquals("Wrong op result status", status, item.getResult().getStatus()); @@ -1274,14 +1410,31 @@ private void assertAttributesFetched(List data) { } } - private void dumpOutput(ExecutionContext output, OperationResult result) throws JAXBException, SchemaException { + void dumpOutput(ExecutionContext output, OperationResult result) throws SchemaException { displayDumpable("output", output.getFinalOutput()); displayValue("stdout", output.getConsoleOutput()); display(result); if (output.getFinalOutput() != null) { - PipelineDataType bean = ModelWebService.prepareXmlData(output.getFinalOutput().getData(), null); + PipelineDataType bean = PipelineData.prepareXmlData(output.getFinalOutput().getData(), null); displayValue("output in XML", prismContext.xmlSerializer().root(new QName("output")).serializeRealValue(bean)); } } + ScriptingExpressionType parseScriptingExpression(File file) throws IOException, SchemaException { + // we cannot specify explicit type parameter here, as the parsed files contain subtypes of ScriptingExpressionType + return prismContext.parserFor(file).parseRealValue(); + } + + private ScriptingExpressionType parseScriptingExpression(String name) throws IOException, SchemaException { + return parseScriptingExpression(getFile(name)); + } + + private ExecuteScriptType parseExecuteScript(File file) throws IOException, SchemaException { + return prismContext.parserFor(file).parseRealValue(ExecuteScriptType.class); + } + + private ExecuteScriptType parseExecuteScript(String name) throws IOException, SchemaException { + return parseExecuteScript(getFile(name)); + } + } diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/scripting/TestScriptingBasicLegacy.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/scripting/TestScriptingBasicLegacy.java new file mode 100644 index 00000000000..cf3e5724dcb --- /dev/null +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/scripting/TestScriptingBasicLegacy.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.model.intest.scripting; + +/** + * Tests legacy ("dynamic") versions of scripting expressions. + */ +public class TestScriptingBasicLegacy extends AbstractBasicScriptingTest { + + @Override + String getSuffix() { + return "-legacy"; + } +} diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/scripting/TestScriptingBasicNew.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/scripting/TestScriptingBasicNew.java new file mode 100644 index 00000000000..e686af77459 --- /dev/null +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/scripting/TestScriptingBasicNew.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.model.intest.scripting; + +import com.evolveum.midpoint.model.impl.scripting.ExecutionContext; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.result.OperationResultStatus; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ScriptingExpressionType; + +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; + +import java.io.File; + +import static org.testng.AssertJUnit.assertEquals; + +/** + * Tests new ("static") versions of scripting expressions. + */ +@Listeners({ com.evolveum.midpoint.tools.testng.AlphabeticalMethodInterceptor.class }) +public class TestScriptingBasicNew extends AbstractBasicScriptingTest { + + private static final File RECOMPUTE_JACK_NEW_TRIGGER_DIRECT_FILE = new File(TEST_DIR, "recompute-jack-new-trigger-direct.xml"); + private static final File RECOMPUTE_JACK_NEW_TRIGGER_OPTIMIZED_FILE = new File(TEST_DIR, "recompute-jack-new-trigger-optimized.xml"); + + private static final File UNASSIGN_CAPTAIN_FROM_JACK_FILE = new File(TEST_DIR, "unassign-captain-from-jack.xml"); + private static final File ASSIGN_CAPTAIN_BY_NAME_TO_JACK_FILE = new File(TEST_DIR, "assign-captain-by-name-to-jack.xml"); + private static final File UNASSIGN_ALL_FROM_JACK_FILE = new File(TEST_DIR, "unassign-all-from-jack.xml"); + + @Override + String getSuffix() { + return ""; + } + + @Test + public void test352RecomputeJackTriggerDirect() throws Exception { + given(); + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ScriptingExpressionType expression = parseScriptingExpression(RECOMPUTE_JACK_NEW_TRIGGER_DIRECT_FILE); + + when(); + evaluator.evaluateExpression(expression, task, result); + Thread.sleep(20); + evaluator.evaluateExpression(expression, task, result); + Thread.sleep(20); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); + + then(); + dumpOutput(output, result); + assertOutputData(output, 1, OperationResultStatus.SUCCESS); + assertSuccess(result); + assertEquals("Triggered recompute of user:c0c010c0-d34d-b33f-f00d-111111111111(jack)\n", output.getConsoleOutput()); + + assertUserAfter(USER_JACK_OID) + .triggers() + .assertTriggers(3); + } + + @Test + public void test353RecomputeJackTriggerOptimized() throws Exception { + given(); + Task task = getTestTask(); + OperationResult result = task.getResult(); + ScriptingExpressionType expression = parseScriptingExpression(RECOMPUTE_JACK_NEW_TRIGGER_OPTIMIZED_FILE); + + ObjectDelta delta = deltaFor(UserType.class) + .item(UserType.F_TRIGGER).replace() + .asObjectDelta(USER_JACK_OID); + executeChanges(delta, null, task, result); + + assertUserBefore(USER_JACK_OID) + .triggers() + .assertTriggers(0); + + when(); + evaluator.evaluateExpression(expression, task, result); + Thread.sleep(20); + evaluator.evaluateExpression(expression, task, result); + Thread.sleep(20); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); + + then(); + dumpOutput(output, result); + assertOutputData(output, 1, OperationResultStatus.SUCCESS); + assertSuccess(result); + assertEquals("Skipped triggering recompute of user:c0c010c0-d34d-b33f-f00d-111111111111(jack) because a trigger was already present\n", output.getConsoleOutput()); + + assertUserAfter(USER_JACK_OID) + .triggers() + .assertTriggers(1); + } + + @Test + public void test361UnassignCaptainFromJack() throws Exception { + given(); + Task task = getTestTask(); + OperationResult result = task.getResult(); + ScriptingExpressionType expression = parseScriptingExpression(UNASSIGN_CAPTAIN_FROM_JACK_FILE); + + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); + + then(); + dumpOutput(output, result); + assertOutputData(output, 1, OperationResultStatus.SUCCESS); + + assertSuccess(result); + //assertEquals("Recomputed user:c0c010c0-d34d-b33f-f00d-111111111111(jack)\n", output.getConsoleOutput()); + assertUserAfterByUsername(USER_JACK_USERNAME) + .assignments() + .single() + .assertResource(RESOURCE_DUMMY_RED_OID); + } + + @Test + public void test363AssignCaptainByNameToJack() throws Exception { + given(); + Task task = getTestTask(); + OperationResult result = task.getResult(); + ScriptingExpressionType expression = parseScriptingExpression(ASSIGN_CAPTAIN_BY_NAME_TO_JACK_FILE); + + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); + + then(); + dumpOutput(output, result); + assertOutputData(output, 1, OperationResultStatus.SUCCESS); + + assertSuccess(result); + //assertEquals("Recomputed user:c0c010c0-d34d-b33f-f00d-111111111111(jack)\n", output.getConsoleOutput()); + assertUserAfterByUsername(USER_JACK_USERNAME) + .assignments() + .assertAssignments(2) + .by() + .targetOid(ROLE_CAPTAIN_OID) + .find() + .end() + .by() + .resourceOid(RESOURCE_DUMMY_RED_OID) + .find() + .end(); + } + + @Test + public void test364UnassignAllFromJack() throws Exception { + given(); + Task task = getTestTask(); + OperationResult result = task.getResult(); + ScriptingExpressionType expression = parseScriptingExpression(UNASSIGN_ALL_FROM_JACK_FILE); + + when(); + ExecutionContext output = evaluator.evaluateExpression(expression, task, result); + + then(); + dumpOutput(output, result); + assertOutputData(output, 1, OperationResultStatus.SUCCESS); + + assertSuccess(result); + //assertEquals("Recomputed user:c0c010c0-d34d-b33f-f00d-111111111111(jack)\n", output.getConsoleOutput()); + assertUserAfterByUsername(USER_JACK_USERNAME) + .assignments() + .assertNone(); + } + +} diff --git a/model/model-intest/src/test/resources/scripting/assign-to-jack.xml b/model/model-intest/src/test/resources/scripting/assign-captain-and-dummy-red-to-jack-legacy.xml similarity index 100% rename from model/model-intest/src/test/resources/scripting/assign-to-jack.xml rename to model/model-intest/src/test/resources/scripting/assign-captain-and-dummy-red-to-jack-legacy.xml diff --git a/model/model-intest/src/test/resources/scripting/assign-captain-and-dummy-red-to-jack.xml b/model/model-intest/src/test/resources/scripting/assign-captain-and-dummy-red-to-jack.xml new file mode 100644 index 00000000000..f33f408a06e --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/assign-captain-and-dummy-red-to-jack.xml @@ -0,0 +1,22 @@ + + + + + c:UserType + + + c:name + jack + + + + + + + diff --git a/model/model-intest/src/test/resources/scripting/assign-captain-by-name-to-jack.xml b/model/model-intest/src/test/resources/scripting/assign-captain-by-name-to-jack.xml new file mode 100644 index 00000000000..ebc233fbc06 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/assign-captain-by-name-to-jack.xml @@ -0,0 +1,29 @@ + + + + + c:UserType + + + c:name + jack + + + + + + + name + Captain + + + + + diff --git a/model/model-intest/src/test/resources/scripting/assign-to-jack-2.xml b/model/model-intest/src/test/resources/scripting/assign-nice-pirate-by-name-to-jack-legacy.xml similarity index 100% rename from model/model-intest/src/test/resources/scripting/assign-to-jack-2.xml rename to model/model-intest/src/test/resources/scripting/assign-nice-pirate-by-name-to-jack-legacy.xml diff --git a/model/model-intest/src/test/resources/scripting/assign-nice-pirate-by-name-to-jack.xml b/model/model-intest/src/test/resources/scripting/assign-nice-pirate-by-name-to-jack.xml new file mode 100644 index 00000000000..a192a1dc5be --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/assign-nice-pirate-by-name-to-jack.xml @@ -0,0 +1,28 @@ + + + + UserType + + + name + jack + + + + + + + name + Nice Pirate + + + + + diff --git a/model/model-intest/src/test/resources/scripting/assign-to-will.xml b/model/model-intest/src/test/resources/scripting/assign-pirate-manager-to-will-legacy.xml similarity index 100% rename from model/model-intest/src/test/resources/scripting/assign-to-will.xml rename to model/model-intest/src/test/resources/scripting/assign-pirate-manager-to-will-legacy.xml diff --git a/model/model-intest/src/test/resources/scripting/assign-pirate-manager-to-will.xml b/model/model-intest/src/test/resources/scripting/assign-pirate-manager-to-will.xml new file mode 100644 index 00000000000..abaabdae2f9 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/assign-pirate-manager-to-will.xml @@ -0,0 +1,21 @@ + + + + + UserType + + + name + willTurner + + + + + + diff --git a/model/model-intest/src/test/resources/scripting/assign-to-will-2.xml b/model/model-intest/src/test/resources/scripting/assign-pirate-relation-captain-to-will-legacy.xml similarity index 100% rename from model/model-intest/src/test/resources/scripting/assign-to-will-2.xml rename to model/model-intest/src/test/resources/scripting/assign-pirate-relation-captain-to-will-legacy.xml diff --git a/model/model-intest/src/test/resources/scripting/assign-pirate-relation-captain-to-will.xml b/model/model-intest/src/test/resources/scripting/assign-pirate-relation-captain-to-will.xml new file mode 100644 index 00000000000..3312f2c5073 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/assign-pirate-relation-captain-to-will.xml @@ -0,0 +1,22 @@ + + + + + UserType + + + name + willTurner + + + + + + diff --git a/model/model-intest/src/test/resources/scripting/assign-to-jack-dry-and-raw-legacy.xml b/model/model-intest/src/test/resources/scripting/assign-to-jack-dry-and-raw-legacy.xml new file mode 100644 index 00000000000..e0b5b5aba1c --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/assign-to-jack-dry-and-raw-legacy.xml @@ -0,0 +1,38 @@ + + + + + c:UserType + + + c:name + jack + + + + assign + + role + 12345678-d34d-b33f-f00d-55555555cccc + + + + dryRun + true + + + options + + true + + + + diff --git a/model/model-intest/src/test/resources/scripting/assign-to-jack-dry-and-raw.xml b/model/model-intest/src/test/resources/scripting/assign-to-jack-dry-and-raw.xml index 5a545c394df..8b3326eedf8 100644 --- a/model/model-intest/src/test/resources/scripting/assign-to-jack-dry-and-raw.xml +++ b/model/model-intest/src/test/resources/scripting/assign-to-jack-dry-and-raw.xml @@ -5,11 +5,8 @@ ~ This work is dual-licensed under the Apache License 2.0 ~ and European Union Public License. See LICENSE file for details. --> - + xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"> c:UserType @@ -17,21 +14,12 @@ jack - - assign - - role - 12345678-d34d-b33f-f00d-55555555cccc - - - dryRun - true - - - options - - true - - - + + + + true + + true + + diff --git a/model/model-intest/src/test/resources/scripting/delete-and-add-jack-legacy.xml b/model/model-intest/src/test/resources/scripting/delete-and-add-jack-legacy.xml new file mode 100644 index 00000000000..311818a4d0e --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/delete-and-add-jack-legacy.xml @@ -0,0 +1,27 @@ + + + + + c:UserType + + + c:name + jack + + + + + delete + + + add + + + diff --git a/model/model-intest/src/test/resources/scripting/delete-and-add-jack.xml b/model/model-intest/src/test/resources/scripting/delete-and-add-jack.xml index 0dc50da0dc7..ee817ed2657 100644 --- a/model/model-intest/src/test/resources/scripting/delete-and-add-jack.xml +++ b/model/model-intest/src/test/resources/scripting/delete-and-add-jack.xml @@ -7,21 +7,16 @@ --> - c:UserType + xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"> + UserType - - c:name - jack - + + name + jack + - - delete - - - add - + + diff --git a/model/model-intest/src/test/resources/scripting/disable-jack-legacy.xml b/model/model-intest/src/test/resources/scripting/disable-jack-legacy.xml new file mode 100644 index 00000000000..fe0ea91f0d4 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/disable-jack-legacy.xml @@ -0,0 +1,24 @@ + + + + + + c:UserType + + + c:name + jack + + + + + disable + + diff --git a/model/model-intest/src/test/resources/scripting/disable-jack.xml b/model/model-intest/src/test/resources/scripting/disable-jack.xml index 245a3fcfec4..cf1a0c34482 100644 --- a/model/model-intest/src/test/resources/scripting/disable-jack.xml +++ b/model/model-intest/src/test/resources/scripting/disable-jack.xml @@ -7,18 +7,15 @@ --> - - c:UserType + xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"> + + UserType - - c:name - jack - + + name + jack + - - - disable - + + diff --git a/model/model-intest/src/test/resources/scripting/echo-legacy.xml b/model/model-intest/src/test/resources/scripting/echo-legacy.xml new file mode 100644 index 00000000000..9b6ec4132f9 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/echo-legacy.xml @@ -0,0 +1,26 @@ + + + + + + + + s1 + 12345678 + + + Jozef + + + + true + + diff --git a/model/model-intest/src/test/resources/scripting/enable-jack-legacy.xml b/model/model-intest/src/test/resources/scripting/enable-jack-legacy.xml new file mode 100644 index 00000000000..3e9e019efd1 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/enable-jack-legacy.xml @@ -0,0 +1,21 @@ + + + + + c:UserType + + + c:name + jack + + + + enable + + diff --git a/model/model-intest/src/test/resources/scripting/enable-jack.xml b/model/model-intest/src/test/resources/scripting/enable-jack.xml index f05d894f5b2..25f5d93b6f1 100644 --- a/model/model-intest/src/test/resources/scripting/enable-jack.xml +++ b/model/model-intest/src/test/resources/scripting/enable-jack.xml @@ -15,7 +15,5 @@ jack - - enable - + diff --git a/model/model-intest/src/test/resources/scripting/generate-passwords-2-legacy.xml b/model/model-intest/src/test/resources/scripting/generate-passwords-2-legacy.xml new file mode 100644 index 00000000000..6487f557c4b --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/generate-passwords-2-legacy.xml @@ -0,0 +1,33 @@ + + + + + + + resolve + + + generate-value + + + name + credentials/password/value + + + + + + + + + + true + + diff --git a/model/model-intest/src/test/resources/scripting/generate-passwords-2.xml b/model/model-intest/src/test/resources/scripting/generate-passwords-2.xml index 6487f557c4b..d1011ebb0ce 100644 --- a/model/model-intest/src/test/resources/scripting/generate-passwords-2.xml +++ b/model/model-intest/src/test/resources/scripting/generate-passwords-2.xml @@ -1,6 +1,6 @@ - - - generate-value - + + name credentials/password/value diff --git a/model/model-intest/src/test/resources/scripting/generate-passwords-3-legacy.xml b/model/model-intest/src/test/resources/scripting/generate-passwords-3-legacy.xml new file mode 100644 index 00000000000..e9c1de5d71f --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/generate-passwords-3-legacy.xml @@ -0,0 +1,44 @@ + + + + + + + resolve + + + generate-value + + items + + + + credentials/password/value + + true + + + + + + name + credentials/password/value + + + + + + + + + true + + diff --git a/model/model-intest/src/test/resources/scripting/generate-passwords-3.xml b/model/model-intest/src/test/resources/scripting/generate-passwords-3.xml index 1e5ed092ecb..38cb19b4771 100644 --- a/model/model-intest/src/test/resources/scripting/generate-passwords-3.xml +++ b/model/model-intest/src/test/resources/scripting/generate-passwords-3.xml @@ -11,23 +11,17 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:api="http://midpoint.evolveum.com/xml/ns/public/common/api-types-3"> - - resolve - - - generate-value - - items - - - - credentials/password/value - - true - - - - + + + + + + credentials/password/value + + true + + + name credentials/password/value diff --git a/model/model-intest/src/test/resources/scripting/generate-passwords-legacy.xml b/model/model-intest/src/test/resources/scripting/generate-passwords-legacy.xml new file mode 100644 index 00000000000..f560ed384df --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/generate-passwords-legacy.xml @@ -0,0 +1,21 @@ + + + + + + c:UserType + + + generate-value + + + name + credentials/password/value + + diff --git a/model/model-intest/src/test/resources/scripting/generate-passwords.xml b/model/model-intest/src/test/resources/scripting/generate-passwords.xml index b90f3125fab..964b9bf26c4 100644 --- a/model/model-intest/src/test/resources/scripting/generate-passwords.xml +++ b/model/model-intest/src/test/resources/scripting/generate-passwords.xml @@ -11,9 +11,7 @@ c:UserType - - generate-value - + name credentials/password/value diff --git a/model/model-intest/src/test/resources/scripting/log-legacy.xml b/model/model-intest/src/test/resources/scripting/log-legacy.xml new file mode 100644 index 00000000000..58afa845fee --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/log-legacy.xml @@ -0,0 +1,18 @@ + + + + + log + + message + Custom message: + + diff --git a/model/model-intest/src/test/resources/scripting/log.xml b/model/model-intest/src/test/resources/scripting/log.xml index deae1629974..21cad803b14 100644 --- a/model/model-intest/src/test/resources/scripting/log.xml +++ b/model/model-intest/src/test/resources/scripting/log.xml @@ -6,13 +6,6 @@ ~ and European Union Public License. See LICENSE file for details. --> - - log - - message - Custom message: - - + + Custom message: + diff --git a/model/model-intest/src/test/resources/scripting/modify-jack-back-legacy.xml b/model/model-intest/src/test/resources/scripting/modify-jack-back-legacy.xml new file mode 100644 index 00000000000..09a035114f9 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/modify-jack-back-legacy.xml @@ -0,0 +1,36 @@ + + + + + + c:UserType + + + c:name + jack + + + + + modify + + delta + + + + replace + c:locality + Caribbean + + + + + diff --git a/model/model-intest/src/test/resources/scripting/modify-jack-back.xml b/model/model-intest/src/test/resources/scripting/modify-jack-back.xml index 6192e188258..56df944630d 100644 --- a/model/model-intest/src/test/resources/scripting/modify-jack-back.xml +++ b/model/model-intest/src/test/resources/scripting/modify-jack-back.xml @@ -7,30 +7,26 @@ --> - c:UserType + UserType - - c:name - jack - + + name + jack + - - - modify - - delta - + + replace - c:locality + locality Caribbean - - + + diff --git a/model/model-intest/src/test/resources/scripting/modify-jack-legacy.xml b/model/model-intest/src/test/resources/scripting/modify-jack-legacy.xml new file mode 100644 index 00000000000..4187922b022 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/modify-jack-legacy.xml @@ -0,0 +1,35 @@ + + + + + + c:UserType + + + c:name + jack + + + + + modify + + delta + + + replace + c:locality + Nowhere + + + + + diff --git a/model/model-intest/src/test/resources/scripting/modify-jack-password-legacy.xml b/model/model-intest/src/test/resources/scripting/modify-jack-password-legacy.xml new file mode 100644 index 00000000000..79c1c52a937 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/modify-jack-password-legacy.xml @@ -0,0 +1,37 @@ + + + + + + c:UserType + + + c:name + jack + + + + + modify + + delta + + + replace + credentials/password/value + + pass1234wor1 + + + + + + diff --git a/model/model-intest/src/test/resources/scripting/modify-jack-password-task-legacy.xml b/model/model-intest/src/test/resources/scripting/modify-jack-password-task-legacy.xml new file mode 100644 index 00000000000..4067112a4f5 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/modify-jack-password-task-legacy.xml @@ -0,0 +1,55 @@ + + + + Task 1555581798624-0-1 + + + + + c:UserType + + + c:name + jack + + + + + modify + + delta + + modify + UserType + + replace + credentials/password/value + + pass1234wor2 + + + + + + + + + 1555581798624-0-1 + + + + runnable + BulkActions + http://midpoint.evolveum.com/xml/ns/public/model/scripting/handler-3 + single + tight + diff --git a/model/model-intest/src/test/resources/scripting/modify-jack-password-task.xml b/model/model-intest/src/test/resources/scripting/modify-jack-password-task.xml index 4067112a4f5..6079fad0381 100644 --- a/model/model-intest/src/test/resources/scripting/modify-jack-password-task.xml +++ b/model/model-intest/src/test/resources/scripting/modify-jack-password-task.xml @@ -23,23 +23,19 @@ - - modify - - delta - - modify - UserType - - replace - credentials/password/value - - pass1234wor2 - - - - - + + + modify + UserType + + replace + credentials/password/value + + pass1234wor2 + + + + diff --git a/model/model-intest/src/test/resources/scripting/modify-jack-password.xml b/model/model-intest/src/test/resources/scripting/modify-jack-password.xml index 79c1c52a937..364d1072e80 100644 --- a/model/model-intest/src/test/resources/scripting/modify-jack-password.xml +++ b/model/model-intest/src/test/resources/scripting/modify-jack-password.xml @@ -19,19 +19,15 @@ - - modify - - delta - - - replace - credentials/password/value - - pass1234wor1 - - - - - + + + + replace + credentials/password/value + + pass1234wor1 + + + + diff --git a/model/model-intest/src/test/resources/scripting/modify-jack.xml b/model/model-intest/src/test/resources/scripting/modify-jack.xml index de93142a6c7..2f3859e0754 100644 --- a/model/model-intest/src/test/resources/scripting/modify-jack.xml +++ b/model/model-intest/src/test/resources/scripting/modify-jack.xml @@ -6,30 +6,23 @@ ~ and European Union Public License. See LICENSE file for details. --> - - - c:UserType - - - c:name - jack - - - - - modify - - delta - - - replace - c:locality - Nowhere - - - - - + + UserType + + + name + jack + + + + + + replace + locality + Nowhere + + + + diff --git a/model/model-intest/src/test/resources/scripting/notification-about-jack-legacy.xml b/model/model-intest/src/test/resources/scripting/notification-about-jack-legacy.xml new file mode 100644 index 00000000000..7207da9b0a6 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/notification-about-jack-legacy.xml @@ -0,0 +1,42 @@ + + + + + c:UserType + + + c:name + jack + + + + notify + + handler + + + + recipient@evolveum.com + + + Ad hoc notification + + + + + dummy:Custom + + + + + diff --git a/model/model-intest/src/test/resources/scripting/notification-about-jack-type2-legacy.xml b/model/model-intest/src/test/resources/scripting/notification-about-jack-type2-legacy.xml new file mode 100644 index 00000000000..577d38f0628 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/notification-about-jack-type2-legacy.xml @@ -0,0 +1,58 @@ + + + + + c:UserType + + + c:name + jack + + + + notify + + subtype + type2 + + + operation + delete + + + status + failure + + + forWholeInput + true + + + handler + + + + recipient@evolveum.com + + + Ad hoc notification 2 + + + + + dummy:Custom + + + + + diff --git a/model/model-intest/src/test/resources/scripting/notification-about-jack-type2.xml b/model/model-intest/src/test/resources/scripting/notification-about-jack-type2.xml index b2b457af8dc..6680a708b37 100644 --- a/model/model-intest/src/test/resources/scripting/notification-about-jack-type2.xml +++ b/model/model-intest/src/test/resources/scripting/notification-about-jack-type2.xml @@ -7,8 +7,8 @@ --> + xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3" + xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"> c:UserType @@ -16,43 +16,27 @@ jack - - notify - - subtype - type2 - - - operation - delete - - - status - failure - - - forWholeInput - true - - - handler - - - - recipient@evolveum.com - - - Ad hoc notification 2 - - - - - dummy:Custom - - - - + + type2 + failure + delete + true + + + + recipient@evolveum.com + + + Ad hoc notification 2 + + + + + dummy:Custom + + + diff --git a/model/model-intest/src/test/resources/scripting/notification-about-jack.xml b/model/model-intest/src/test/resources/scripting/notification-about-jack.xml index f77bc7d4060..a9c1ca17b4f 100644 --- a/model/model-intest/src/test/resources/scripting/notification-about-jack.xml +++ b/model/model-intest/src/test/resources/scripting/notification-about-jack.xml @@ -6,37 +6,32 @@ ~ and European Union Public License. See LICENSE file for details. --> - - c:UserType + + UserType - c:name + name jack - - notify - - handler - - - - recipient@evolveum.com - - - Ad hoc notification - - - - - dummy:Custom - - - - + + + + + recipient@evolveum.com + + + Ad hoc notification + + + + + dummy:Custom + + + diff --git a/model/model-intest/src/test/resources/scripting/purge-dummy-black-schema-legacy.xml b/model/model-intest/src/test/resources/scripting/purge-dummy-black-schema-legacy.xml new file mode 100644 index 00000000000..1959d70c22a --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/purge-dummy-black-schema-legacy.xml @@ -0,0 +1,21 @@ + + + + + c:ResourceType + + + c:name + Dummy Resource Black + + + + purge-schema + + diff --git a/model/model-intest/src/test/resources/scripting/purge-dummy-black-schema.xml b/model/model-intest/src/test/resources/scripting/purge-dummy-black-schema.xml index c5cef055f6e..45f9e61f4b6 100644 --- a/model/model-intest/src/test/resources/scripting/purge-dummy-black-schema.xml +++ b/model/model-intest/src/test/resources/scripting/purge-dummy-black-schema.xml @@ -6,16 +6,13 @@ ~ and European Union Public License. See LICENSE file for details. --> - - c:ResourceType + + ResourceType - c:name + name Dummy Resource Black - - purge-schema - + diff --git a/model/model-intest/src/test/resources/scripting/recompute-jack-legacy.xml b/model/model-intest/src/test/resources/scripting/recompute-jack-legacy.xml new file mode 100644 index 00000000000..491279fe82a --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/recompute-jack-legacy.xml @@ -0,0 +1,21 @@ + + + + + c:UserType + + + c:name + jack + + + + recompute + + diff --git a/model/model-intest/src/test/resources/scripting/recompute-jack-new-trigger-direct.xml b/model/model-intest/src/test/resources/scripting/recompute-jack-new-trigger-direct.xml new file mode 100644 index 00000000000..57fe5a90fd5 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/recompute-jack-new-trigger-direct.xml @@ -0,0 +1,22 @@ + + + + + UserType + + + + name + jack + + + + + + + diff --git a/model/model-intest/src/test/resources/scripting/recompute-jack-new-trigger-optimized.xml b/model/model-intest/src/test/resources/scripting/recompute-jack-new-trigger-optimized.xml new file mode 100644 index 00000000000..bbbd05a20f0 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/recompute-jack-new-trigger-optimized.xml @@ -0,0 +1,24 @@ + + + + + UserType + + + + name + jack + + + + + + PT5M + + + diff --git a/model/model-intest/src/test/resources/scripting/recompute-jack.xml b/model/model-intest/src/test/resources/scripting/recompute-jack.xml index 6e58636662c..f6a38a9c56a 100644 --- a/model/model-intest/src/test/resources/scripting/recompute-jack.xml +++ b/model/model-intest/src/test/resources/scripting/recompute-jack.xml @@ -6,16 +6,15 @@ ~ and European Union Public License. See LICENSE file for details. --> - - c:UserType - - - c:name - jack - - - - recompute - + + UserType + + + + name + jack + + + + diff --git a/model/model-intest/src/test/resources/scripting/resume-suspended-tasks-legacy.xml b/model/model-intest/src/test/resources/scripting/resume-suspended-tasks-legacy.xml new file mode 100644 index 00000000000..74adc3decf7 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/resume-suspended-tasks-legacy.xml @@ -0,0 +1,25 @@ + + + + + TaskType + + + + name + Task to resume + + + + + resume + + + diff --git a/model/model-intest/src/test/resources/scripting/resume-suspended-tasks.xml b/model/model-intest/src/test/resources/scripting/resume-suspended-tasks.xml index f35941db8f0..9a0484b1948 100644 --- a/model/model-intest/src/test/resources/scripting/resume-suspended-tasks.xml +++ b/model/model-intest/src/test/resources/scripting/resume-suspended-tasks.xml @@ -7,31 +7,17 @@ --> TaskType - - - category - Workflow - - - handlerUri - - http://midpoint.evolveum.com/xml/ns/public/task/noop/handler-3 - - - executionStatus - suspended - - + + name + Task to resume + - - resume - + diff --git a/model/model-intest/src/test/resources/scripting/scripting-users-in-background-assign-legacy.xml b/model/model-intest/src/test/resources/scripting/scripting-users-in-background-assign-legacy.xml new file mode 100644 index 00000000000..4421471d64a --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/scripting-users-in-background-assign-legacy.xml @@ -0,0 +1,61 @@ + + + + + + + c:UserType + + + + name + administrator + + + + + + execute-script + + script + + + import com.evolveum.midpoint.schema.constants.* + import com.evolveum.midpoint.xml.ns._public.common.common_3.* + import com.evolveum.midpoint.model.api.* + def roleToAssignOid = '12345111-1111-2222-1111-121212111112' // role-empty + + log.info('### {} - {}', input.name, input.fullName) + + assignmentsToAdd = [] + newAssignment = new AssignmentType() + targetRef = new ObjectReferenceType() + targetRef.setOid(roleToAssignOid) + targetRef.setType(RoleType.COMPLEX_TYPE) + newAssignment.setTargetRef(targetRef) + assignmentsToAdd.add(newAssignment.asPrismContainerValue()) + + // Suspicious code, see MID-4234. It is working here almost by chance. + // E.g. if executed for user jack, it would fail because of SchemaException. + // More correct is to replace FocusType.class with input.class here. + def delta = midpoint.deltaFor(FocusType.class) + .item(FocusType.F_ASSIGNMENT).add(assignmentsToAdd) + .asObjectDelta(input.oid) + + log.info('### Going to execute delta = {}', delta.debugDump()) + midpoint.modifyObject(delta) + log.info('### Finished: {} - {}', input.getName(), input?.getFullName()) + + + + + + diff --git a/model/model-intest/src/test/resources/scripting/scripting-users-in-background-assign.xml b/model/model-intest/src/test/resources/scripting/scripting-users-in-background-assign.xml index cf1d9b73505..f666d163685 100644 --- a/model/model-intest/src/test/resources/scripting/scripting-users-in-background-assign.xml +++ b/model/model-intest/src/test/resources/scripting/scripting-users-in-background-assign.xml @@ -8,8 +8,8 @@ + xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3" + xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"> c:UserType @@ -22,40 +22,36 @@ - - execute-script - - script - - - import com.evolveum.midpoint.schema.constants.* - import com.evolveum.midpoint.xml.ns._public.common.common_3.* - import com.evolveum.midpoint.model.api.* - def roleToAssignOid = '12345111-1111-2222-1111-121212111112' // role-empty + + + + import com.evolveum.midpoint.schema.constants.* + import com.evolveum.midpoint.xml.ns._public.common.common_3.* + import com.evolveum.midpoint.model.api.* + def roleToAssignOid = '12345111-1111-2222-1111-121212111112' // role-empty - log.info('### {} - {}', input.name, input.fullName) + log.info('### {} - {}', input.name, input.fullName) - assignmentsToAdd = [] - newAssignment = new AssignmentType() - targetRef = new ObjectReferenceType() - targetRef.setOid(roleToAssignOid) - targetRef.setType(RoleType.COMPLEX_TYPE) - newAssignment.setTargetRef(targetRef) - assignmentsToAdd.add(newAssignment.asPrismContainerValue()) + assignmentsToAdd = [] + newAssignment = new AssignmentType() + targetRef = new ObjectReferenceType() + targetRef.setOid(roleToAssignOid) + targetRef.setType(RoleType.COMPLEX_TYPE) + newAssignment.setTargetRef(targetRef) + assignmentsToAdd.add(newAssignment.asPrismContainerValue()) - // Suspicious code, see MID-4234. It is working here almost by chance. - // E.g. if executed for user jack, it would fail because of SchemaException. - // More correct is to replace FocusType.class with input.class here. - def delta = midpoint.deltaFor(FocusType.class) - .item(FocusType.F_ASSIGNMENT).add(assignmentsToAdd) - .asObjectDelta(input.oid) + // Suspicious code, see MID-4234. It is working here almost by chance. + // E.g. if executed for user jack, it would fail because of SchemaException. + // More correct is to replace FocusType.class with input.class here. + def delta = midpoint.deltaFor(FocusType.class) + .item(FocusType.F_ASSIGNMENT).add(assignmentsToAdd) + .asObjectDelta(input.oid) - log.info('### Going to execute delta = {}', delta.debugDump()) - midpoint.modifyObject(delta) - log.info('### Finished: {} - {}', input.getName(), input?.getFullName()) - - - - + log.info('### Going to execute delta = {}', delta.debugDump()) + midpoint.modifyObject(delta) + log.info('### Finished: {} - {}', input.getName(), input?.getFullName()) + + + diff --git a/model/model-intest/src/test/resources/scripting/scripting-users-in-background-iterative-task-legacy.xml b/model/model-intest/src/test/resources/scripting/scripting-users-in-background-iterative-task-legacy.xml new file mode 100644 index 00000000000..5dbcbf0c579 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/scripting-users-in-background-iterative-task-legacy.xml @@ -0,0 +1,44 @@ + + + + Change description task template (iterative) + + + + execute-script + + script + + + import com.evolveum.midpoint.xml.ns._public.common.common_3.* + + log.info('Modifying user {}', input) + def deltas = midpoint.deltaFor(UserType.class) + .item(UserType.F_DESCRIPTION) + .replace('hello ' + basic.stringify(input.name)) + .asObjectDeltas(input.oid) + log.info('Change:\n{}', deltas.iterator().next().debugDump()) + midpoint.executeChanges(deltas, null) + + + + + + UserType + + + runnable + BulkActions + http://midpoint.evolveum.com/xml/ns/public/model/iterative-scripting/handler-3 + single + diff --git a/model/model-intest/src/test/resources/scripting/scripting-users-in-background-iterative-task.xml b/model/model-intest/src/test/resources/scripting/scripting-users-in-background-iterative-task.xml index 5dbcbf0c579..0e94ec5662f 100644 --- a/model/model-intest/src/test/resources/scripting/scripting-users-in-background-iterative-task.xml +++ b/model/model-intest/src/test/resources/scripting/scripting-users-in-background-iterative-task.xml @@ -6,33 +6,26 @@ ~ and European Union Public License. See LICENSE file for details. --> Change description task template (iterative) - - execute-script - - script - - - import com.evolveum.midpoint.xml.ns._public.common.common_3.* + + + + import com.evolveum.midpoint.xml.ns._public.common.common_3.* - log.info('Modifying user {}', input) - def deltas = midpoint.deltaFor(UserType.class) - .item(UserType.F_DESCRIPTION) - .replace('hello ' + basic.stringify(input.name)) - .asObjectDeltas(input.oid) - log.info('Change:\n{}', deltas.iterator().next().debugDump()) - midpoint.executeChanges(deltas, null) - - - - + log.info('Modifying user {}', input) + def deltas = midpoint.deltaFor(UserType.class) + .item(UserType.F_DESCRIPTION) + .replace('hello ' + basic.stringify(input.name)) + .asObjectDeltas(input.oid) + log.info('Change:\n{}', deltas.iterator().next().debugDump()) + midpoint.executeChanges(deltas, null) + + + UserType diff --git a/model/model-intest/src/test/resources/scripting/scripting-users-in-background-legacy.xml b/model/model-intest/src/test/resources/scripting/scripting-users-in-background-legacy.xml new file mode 100644 index 00000000000..bba7508724b --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/scripting-users-in-background-legacy.xml @@ -0,0 +1,61 @@ + + + + + + + c:UserType + + + + name + + $userName + + + + + + + execute-script + + script + + + import com.evolveum.midpoint.xml.ns._public.common.common_3.* + + log.info('Modifying user {}', input) + def deltas = midpoint.deltaFor(UserType.class) + .item(UserType.F_DESCRIPTION) + .replace(userDescription) + .asObjectDeltas(input.oid) + log.info('Change:\n{}', deltas.iterator().next().debugDump()) + midpoint.executeChanges(deltas, null) + + + + + + + + userName + + $task/extension/userName + + + + userDescription + + $task/extension/userDescription + + + + diff --git a/model/model-intest/src/test/resources/scripting/scripting-users-in-background-task.xml b/model/model-intest/src/test/resources/scripting/scripting-users-in-background-task.xml index f8e04737b80..c769d930078 100644 --- a/model/model-intest/src/test/resources/scripting/scripting-users-in-background-task.xml +++ b/model/model-intest/src/test/resources/scripting/scripting-users-in-background-task.xml @@ -28,25 +28,21 @@ - - execute-script - - script - - - import com.evolveum.midpoint.xml.ns._public.common.common_3.* + + + + import com.evolveum.midpoint.xml.ns._public.common.common_3.* - log.info('Modifying user {}', input) - def deltas = midpoint.deltaFor(UserType.class) - .item(UserType.F_DESCRIPTION) - .replace(userDescription) - .asObjectDeltas(input.oid) - log.info('Change:\n{}', deltas.iterator().next().debugDump()) - midpoint.executeChanges(deltas, null) - - - - + log.info('Modifying user {}', input) + def deltas = midpoint.deltaFor(UserType.class) + .item(UserType.F_DESCRIPTION) + .replace(userDescription) + .asObjectDeltas(input.oid) + log.info('Change:\n{}', deltas.iterator().next().debugDump()) + midpoint.executeChanges(deltas, null) + + + diff --git a/model/model-intest/src/test/resources/scripting/scripting-users-in-background.xml b/model/model-intest/src/test/resources/scripting/scripting-users-in-background.xml index 0a5ea29cc2f..d92a1760fbd 100644 --- a/model/model-intest/src/test/resources/scripting/scripting-users-in-background.xml +++ b/model/model-intest/src/test/resources/scripting/scripting-users-in-background.xml @@ -7,54 +7,49 @@ --> + xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3" + xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"> - c:UserType + UserType name - - $userName - + + $userName + - - execute-script - - script - - - import com.evolveum.midpoint.xml.ns._public.common.common_3.* + + + + import com.evolveum.midpoint.xml.ns._public.common.common_3.* - log.info('Modifying user {}', input) - def deltas = midpoint.deltaFor(UserType.class) - .item(UserType.F_DESCRIPTION) - .replace(userDescription) - .asObjectDeltas(input.oid) - log.info('Change:\n{}', deltas.iterator().next().debugDump()) - midpoint.executeChanges(deltas, null) - - - - + log.info('Modifying user {}', input) + def deltas = midpoint.deltaFor(UserType.class) + .item(UserType.F_DESCRIPTION) + .replace(userDescription) + .asObjectDeltas(input.oid) + log.info('Change:\n{}', deltas.iterator().next().debugDump()) + midpoint.executeChanges(deltas, null) + + + userName - $task/extension/userName + $task/extension/userName userDescription - $task/extension/userDescription + $task/extension/userDescription diff --git a/model/model-intest/src/test/resources/scripting/scripting-users-legacy.xml b/model/model-intest/src/test/resources/scripting/scripting-users-legacy.xml new file mode 100644 index 00000000000..3fdd6accb4a --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/scripting-users-legacy.xml @@ -0,0 +1,32 @@ + + + + + + c:UserType + + + execute-script + + script + + + cloned = input.clone() + cloned.setDescription('Test') + cloned + + + + + outputItem + UserType + + + diff --git a/model/model-intest/src/test/resources/scripting/scripting-users.xml b/model/model-intest/src/test/resources/scripting/scripting-users.xml index b2122bd89d2..0281468cc1e 100644 --- a/model/model-intest/src/test/resources/scripting/scripting-users.xml +++ b/model/model-intest/src/test/resources/scripting/scripting-users.xml @@ -7,26 +7,18 @@ --> - - c:UserType - - - execute-script - - script - - - cloned = input.clone() - cloned.setDescription('Test') - cloned - - - - - outputItem - UserType - - + xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"> + + UserType + + + + + cloned = input.clone() + cloned.setDescription('Test') + cloned + + + UserType + diff --git a/model/model-intest/src/test/resources/scripting/search-for-shadows-nofetch-legacy.xml b/model/model-intest/src/test/resources/scripting/search-for-shadows-nofetch-legacy.xml new file mode 100644 index 00000000000..ec620d45401 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/search-for-shadows-nofetch-legacy.xml @@ -0,0 +1,32 @@ + + + + + c:ShadowType + + + + c:resourceRef + + + + c:objectClass + ri:AccountObjectClass + + + + + + + true + + + + diff --git a/model/model-intest/src/test/resources/scripting/start-tasks-from-template-legacy.xml b/model/model-intest/src/test/resources/scripting/start-tasks-from-template-legacy.xml new file mode 100644 index 00000000000..9111e13df43 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/start-tasks-from-template-legacy.xml @@ -0,0 +1,37 @@ + + + + + + execute-script + + script + + + import javax.xml.namespace.* + def newTask1 = midpoint.submitTaskFromTemplate('79dacdf7-2bc9-4eef-9c63-08d53d2392c3', + [(new QName('userName')):'jack', (new QName('userDescription')):'new desc jack']) + def newTask2 = midpoint.submitTaskFromTemplate('79dacdf7-2bc9-4eef-9c63-08d53d2392c3', + [(new QName('userName')):'administrator', (new QName('userDescription')):'new desc admin']) + return [newTask1, newTask2] + + + + + outputItem + http://midpoint.evolveum.com/xml/ns/public/common/common-3#task + + + forWholeInput + true + + + diff --git a/model/model-intest/src/test/resources/scripting/start-tasks-from-template.xml b/model/model-intest/src/test/resources/scripting/start-tasks-from-template.xml index 9111e13df43..dd1e42de3e6 100644 --- a/model/model-intest/src/test/resources/scripting/start-tasks-from-template.xml +++ b/model/model-intest/src/test/resources/scripting/start-tasks-from-template.xml @@ -8,30 +8,19 @@ - - execute-script - - script - - - import javax.xml.namespace.* - def newTask1 = midpoint.submitTaskFromTemplate('79dacdf7-2bc9-4eef-9c63-08d53d2392c3', - [(new QName('userName')):'jack', (new QName('userDescription')):'new desc jack']) - def newTask2 = midpoint.submitTaskFromTemplate('79dacdf7-2bc9-4eef-9c63-08d53d2392c3', - [(new QName('userName')):'administrator', (new QName('userDescription')):'new desc admin']) - return [newTask1, newTask2] - - - - - outputItem - http://midpoint.evolveum.com/xml/ns/public/common/common-3#task - - - forWholeInput - true - - + xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"> + + + + import javax.xml.namespace.* + def newTask1 = midpoint.submitTaskFromTemplate('79dacdf7-2bc9-4eef-9c63-08d53d2392c3', + [(new QName('userName')):'jack', (new QName('userDescription')):'new desc jack']) + def newTask2 = midpoint.submitTaskFromTemplate('79dacdf7-2bc9-4eef-9c63-08d53d2392c3', + [(new QName('userName')):'administrator', (new QName('userDescription')):'new desc admin']) + return [newTask1, newTask2] + + + true + task + diff --git a/model/model-intest/src/test/resources/scripting/task-to-keep-suspended.xml b/model/model-intest/src/test/resources/scripting/task-to-keep-suspended.xml index 31bdcd63aaa..3f81c4472da 100644 --- a/model/model-intest/src/test/resources/scripting/task-to-keep-suspended.xml +++ b/model/model-intest/src/test/resources/scripting/task-to-keep-suspended.xml @@ -11,22 +11,17 @@ xmlns:org="http://midpoint.evolveum.com/xml/ns/public/common/org-3" oid="e6ad137e-23f6-444d-9478-c10a0b255b68" version="1"> - Approval and execution of: Assigning role "abc" to user "def" (old) + Task to keep suspended 2222222222222-0-1 http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user suspended - Workflow http://midpoint.evolveum.com/xml/ns/public/task/noop/handler-3 - partial_error - 2018-01-02T12:24:33.635+02:00 - 2018-01-02T12:25:46.587+02:00 + 2018-04-11T12:24:33.635+02:00 + 2018-04-11T12:25:46.587+02:00 single tight - - primary - diff --git a/model/model-intest/src/test/resources/scripting/task-to-resume.xml b/model/model-intest/src/test/resources/scripting/task-to-resume.xml index 261c109d2d1..ad2b0ef26b7 100644 --- a/model/model-intest/src/test/resources/scripting/task-to-resume.xml +++ b/model/model-intest/src/test/resources/scripting/task-to-resume.xml @@ -11,22 +11,17 @@ xmlns:org="http://midpoint.evolveum.com/xml/ns/public/common/org-3" oid="c77c458d-0719-4bef-aa8d-dbf0460cd77c" version="35"> - Approval and execution of: Assigning role "abc" to user "def" + Task to resume 1522830887681-0-1 http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user suspended - Workflow http://midpoint.evolveum.com/xml/ns/public/task/noop/handler-3 - partial_error 2018-04-11T12:24:33.635+02:00 2018-04-11T12:25:46.587+02:00 single tight - - primary - diff --git a/model/model-intest/src/test/resources/scripting/test-dummy-resource-legacy.xml b/model/model-intest/src/test/resources/scripting/test-dummy-resource-legacy.xml new file mode 100644 index 00000000000..9627548d1e8 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/test-dummy-resource-legacy.xml @@ -0,0 +1,21 @@ + + + + + c:ResourceType + + + c:name + Dummy Resource + + + + test-resource + + diff --git a/model/model-intest/src/test/resources/scripting/test-dummy-resource.xml b/model/model-intest/src/test/resources/scripting/test-dummy-resource.xml index 92dde3f9941..bd0950860c6 100644 --- a/model/model-intest/src/test/resources/scripting/test-dummy-resource.xml +++ b/model/model-intest/src/test/resources/scripting/test-dummy-resource.xml @@ -15,7 +15,5 @@ Dummy Resource - - test-resource - + diff --git a/model/model-intest/src/test/resources/scripting/unassign-all-from-jack.xml b/model/model-intest/src/test/resources/scripting/unassign-all-from-jack.xml new file mode 100644 index 00000000000..8de65d911b2 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/unassign-all-from-jack.xml @@ -0,0 +1,23 @@ + + + + + UserType + + + name + jack + + + + + + + + diff --git a/model/model-intest/src/test/resources/scripting/unassign-captain-from-jack.xml b/model/model-intest/src/test/resources/scripting/unassign-captain-from-jack.xml new file mode 100644 index 00000000000..87f5adc0718 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/unassign-captain-from-jack.xml @@ -0,0 +1,26 @@ + + + + + UserType + + + name + jack + + + + + + targetRef + + + + + diff --git a/model/model-intest/src/test/resources/scripting/unassign-from-will-3.xml b/model/model-intest/src/test/resources/scripting/unassign-dummy-resource-from-will-legacy.xml similarity index 100% rename from model/model-intest/src/test/resources/scripting/unassign-from-will-3.xml rename to model/model-intest/src/test/resources/scripting/unassign-dummy-resource-from-will-legacy.xml diff --git a/model/model-intest/src/test/resources/scripting/unassign-dummy-resource-from-will.xml b/model/model-intest/src/test/resources/scripting/unassign-dummy-resource-from-will.xml new file mode 100644 index 00000000000..85b6345e713 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/unassign-dummy-resource-from-will.xml @@ -0,0 +1,26 @@ + + + + + UserType + + + name + willTurner + + + + + + construction/resourceRef + + + + + diff --git a/model/model-intest/src/test/resources/scripting/unassign-from-will.xml b/model/model-intest/src/test/resources/scripting/unassign-pirate-default-from-will-legacy.xml similarity index 95% rename from model/model-intest/src/test/resources/scripting/unassign-from-will.xml rename to model/model-intest/src/test/resources/scripting/unassign-pirate-default-from-will-legacy.xml index 9fef792f053..cb332731f1b 100644 --- a/model/model-intest/src/test/resources/scripting/unassign-from-will.xml +++ b/model/model-intest/src/test/resources/scripting/unassign-pirate-default-from-will-legacy.xml @@ -23,5 +23,6 @@ role 12345678-d34d-b33f-f00d-555555556666 + diff --git a/model/model-intest/src/test/resources/scripting/unassign-pirate-default-from-will.xml b/model/model-intest/src/test/resources/scripting/unassign-pirate-default-from-will.xml new file mode 100644 index 00000000000..e5500627da2 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/unassign-pirate-default-from-will.xml @@ -0,0 +1,25 @@ + + + + UserType + + + name + willTurner + + + + + + targetRef + + + + + diff --git a/model/model-intest/src/test/resources/scripting/unassign-from-will-2.xml b/model/model-intest/src/test/resources/scripting/unassign-pirate-manager-and-owner-from-will-legacy.xml similarity index 100% rename from model/model-intest/src/test/resources/scripting/unassign-from-will-2.xml rename to model/model-intest/src/test/resources/scripting/unassign-pirate-manager-and-owner-from-will-legacy.xml diff --git a/model/model-intest/src/test/resources/scripting/unassign-pirate-manager-and-owner-from-will.xml b/model/model-intest/src/test/resources/scripting/unassign-pirate-manager-and-owner-from-will.xml new file mode 100644 index 00000000000..e9d567e16e6 --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/unassign-pirate-manager-and-owner-from-will.xml @@ -0,0 +1,32 @@ + + + + + UserType + + + name + willTurner + + + + + + + targetRef + + + + targetRef + + + + + + diff --git a/model/model-intest/src/test/resources/scripting/use-variables-legacy.xml b/model/model-intest/src/test/resources/scripting/use-variables-legacy.xml new file mode 100644 index 00000000000..53b1411cd0f --- /dev/null +++ b/model/model-intest/src/test/resources/scripting/use-variables-legacy.xml @@ -0,0 +1,88 @@ + + + + + + + execute-script + + script + + + log.info('=== Variables ===') + this.binding.variables.each {k,v -> log.info('{} = {}', k, v)} + + if (userName != 'user1') { + return 'Wrong username: ' + userName + } + if (new java.util.HashSet(groups) != ['group1', 'group2', 'group3'] as Set) { + return 'Wrong groups: ' + groups + } + if (academicYear != '2017/2018') { + return 'Wrong academic year: ' + academicYear + } + if (calendarYear != 2017) { + return 'Wrong calendar year: ' + calendarYear + } + if (!(deadline instanceof javax.xml.datatype.XMLGregorianCalendar)) { + return 'deadline missing or of wrong type: ' + deadline?.class + } + return 'ok' + + + + + forWholeInput + true + + + outputItem + http://midpoint.evolveum.com/xml/ns/public/common/common-3#description + + + + + userName + + $task/extension/userName + + + + groups + + $task/extension/studyGroup + + + + academicYear + + 2017/2018 + + + + calendarYear + + 2017 + + + + deadline + xsd:dateTime + + + + basic.fromNow("P3D") + + + + + + diff --git a/model/model-intest/src/test/resources/scripting/use-variables.xml b/model/model-intest/src/test/resources/scripting/use-variables.xml index 53b1411cd0f..a43402c82fa 100644 --- a/model/model-intest/src/test/resources/scripting/use-variables.xml +++ b/model/model-intest/src/test/resources/scripting/use-variables.xml @@ -9,45 +9,36 @@ - - execute-script - - script - - - log.info('=== Variables ===') - this.binding.variables.each {k,v -> log.info('{} = {}', k, v)} + + + + log.info('=== Variables ===') + this.binding.variables.each {k,v -> log.info('{} = {}', k, v)} - if (userName != 'user1') { - return 'Wrong username: ' + userName - } - if (new java.util.HashSet(groups) != ['group1', 'group2', 'group3'] as Set) { - return 'Wrong groups: ' + groups - } - if (academicYear != '2017/2018') { - return 'Wrong academic year: ' + academicYear - } - if (calendarYear != 2017) { - return 'Wrong calendar year: ' + calendarYear - } - if (!(deadline instanceof javax.xml.datatype.XMLGregorianCalendar)) { - return 'deadline missing or of wrong type: ' + deadline?.class - } - return 'ok' - - - - - forWholeInput - true - - - outputItem - http://midpoint.evolveum.com/xml/ns/public/common/common-3#description - - + if (userName != 'user1') { + return 'Wrong username: ' + userName + } + if (new java.util.HashSet(groups) != ['group1', 'group2', 'group3'] as Set) { + return 'Wrong groups: ' + groups + } + if (academicYear != '2017/2018') { + return 'Wrong academic year: ' + academicYear + } + if (calendarYear != 2017) { + return 'Wrong calendar year: ' + calendarYear + } + if (!(deadline instanceof javax.xml.datatype.XMLGregorianCalendar)) { + return 'deadline missing or of wrong type: ' + deadline?.class + } + return 'ok' + + + true + xsd:string + userName diff --git a/model/model-intest/src/test/resources/tracing/resource-illegal.xml b/model/model-intest/src/test/resources/tracing/resource-illegal.xml new file mode 100644 index 00000000000..75bac3a7ff0 --- /dev/null +++ b/model/model-intest/src/test/resources/tracing/resource-illegal.xml @@ -0,0 +1,109 @@ + + + + + + Dummy Resource + + + + + connectorType + com.evolveum.icf.dummy.connector.DummyConnector + + + connectorVersion + 2.0 + + + + + + + + illegal + + + + false + false + false + + + + + + + account + default + true + ri:AccountObjectClass + + icfs:name + + strong + + name + + + + + ri:fullname + Full Name + + + + + + + + + + + ri:AccountObjectClass + account + default + + + name + + $account/attributes/icfs:name + + + + + linked + true + + + deleted + + http://midpoint.evolveum.com/xml/ns/public/model/action-3#unlink + + + + unlinked + + http://midpoint.evolveum.com/xml/ns/public/model/action-3#link + + + + unmatched + + + + diff --git a/model/model-intest/src/test/resources/tracing/role-illegal.xml b/model/model-intest/src/test/resources/tracing/role-illegal.xml new file mode 100644 index 00000000000..cbe381cae7e --- /dev/null +++ b/model/model-intest/src/test/resources/tracing/role-illegal.xml @@ -0,0 +1,29 @@ + + + + illegal + + + + strong + + name + + + + + + + + + diff --git a/model/model-intest/src/test/resources/tracing/system-configuration.xml b/model/model-intest/src/test/resources/tracing/system-configuration.xml new file mode 100644 index 00000000000..c9eecb1c115 --- /dev/null +++ b/model/model-intest/src/test/resources/tracing/system-configuration.xml @@ -0,0 +1,16 @@ + + + + SystemConfiguration + + + true + + + diff --git a/model/model-intest/src/test/resources/tracing/user-joe.xml b/model/model-intest/src/test/resources/tracing/user-joe.xml new file mode 100644 index 00000000000..1eefaf9b4c1 --- /dev/null +++ b/model/model-intest/src/test/resources/tracing/user-joe.xml @@ -0,0 +1,11 @@ + + + + joe + diff --git a/model/model-intest/testng-integration-full.xml b/model/model-intest/testng-integration-full.xml index 4b53fe97af3..bd661ce986c 100644 --- a/model/model-intest/testng-integration-full.xml +++ b/model/model-intest/testng-integration-full.xml @@ -65,6 +65,7 @@ + @@ -105,7 +106,8 @@ - + + @@ -125,7 +127,6 @@ - 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 077c4edaaeb..3607ba91b4f 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 @@ -7,6 +7,7 @@ package com.evolveum.midpoint.model.test; import static java.util.Collections.singleton; +import static org.assertj.core.api.Assertions.assertThat; import static org.testng.AssertJUnit.*; import static com.evolveum.midpoint.prism.PrismObject.asObjectableList; @@ -128,7 +129,6 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import com.evolveum.midpoint.xml.ns._public.model.model_3.ModelPortType; import com.evolveum.prism.xml.ns._public.types_3.*; /** @@ -164,7 +164,6 @@ public abstract class AbstractModelIntegrationTest extends AbstractIntegrationTe @Autowired protected ModelDiagnosticService modelDiagnosticService; @Autowired protected DashboardService dashboardService; @Autowired protected ModelAuditService modelAuditService; - @Autowired protected ModelPortType modelWeb; @Autowired @Qualifier("cacheRepositoryService") @@ -1662,6 +1661,32 @@ protected void assignPolicyRule(Class type, String focu assign(type, focusOid, assignmentType, task, result); } + protected void assign(TestResource assignee, TestResource assigned, QName relation, ModelExecuteOptions options, + Task task, OperationResult result) throws SchemaException, CommunicationException, ObjectAlreadyExistsException, + ExpressionEvaluationException, PolicyViolationException, SecurityViolationException, ConfigurationException, ObjectNotFoundException { + ObjectDelta delta = deltaFor(assignee.getObjectClass()) + .item(UserType.F_ASSIGNMENT) + .add(ObjectTypeUtil.createAssignmentTo(assigned.object, relation)) + .asObjectDelta(assignee.oid); + executeChanges(delta, options, task, result); + } + + protected void unassignIfSingle(TestResource assignee, TestResource assigned, QName relation, ModelExecuteOptions options, + Task task, OperationResult result) throws SchemaException, CommunicationException, ObjectAlreadyExistsException, + ExpressionEvaluationException, PolicyViolationException, SecurityViolationException, ConfigurationException, ObjectNotFoundException { + List assignments = ((AssignmentHolderType) assignee.getObjectable()).getAssignment().stream() + .filter(a -> a.getTargetRef() != null && assigned.oid.equals(a.getTargetRef().getOid()) + && QNameUtil.match(a.getTargetRef().getRelation(), relation)) + .collect(Collectors.toList()); + assertThat(assignments).size().as("# of assignments of " + assigned).isEqualTo(1); + AssignmentType assignment = MiscUtil.extractSingleton(assignments); + ObjectDelta delta = deltaFor(assignee.getObjectClass()) + .item(UserType.F_ASSIGNMENT) + .delete(assignment.clone()) + .asObjectDelta(assignee.oid); + executeChanges(delta, options, task, result); + } + protected void assign(Class type, String focusOid, AssignmentType assignmentType, Task task, OperationResult result) throws SchemaException, ObjectAlreadyExistsException, ObjectNotFoundException, @@ -3880,9 +3905,9 @@ protected void addTask(File file) throws SchemaException, IOException, ObjectAlr taskManager.addTask(prismContext.parseObject(file), new OperationResult("addTask")); } - protected void addObject(File file) throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, PolicyViolationException, SecurityViolationException, IOException { + protected String addObject(File file) throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, PolicyViolationException, SecurityViolationException, IOException { PrismObject object = prismContext.parseObject(file); - addObject(object); + return addObject(object); } protected PrismObject addObject(File file, Task task, OperationResult result) throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, PolicyViolationException, SecurityViolationException, IOException { @@ -5980,8 +6005,8 @@ protected ResourceAsserter assertResource(String oid, String message) thro return assertResource(resource, message); } - protected ResourceAsserter assertResource(PrismObject user, String message) { - ResourceAsserter asserter = ResourceAsserter.forResource(user, message); + protected ResourceAsserter assertResource(PrismObject resource, String message) { + ResourceAsserter asserter = ResourceAsserter.forResource(resource, message); initializeAsserter(asserter); return asserter; } @@ -5991,6 +6016,11 @@ protected ResourceAsserter assertResourceAfter(String oid) throws ObjectNo .display(); } + protected ResourceAsserter assertResourceBefore(String oid) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { + return assertResource(oid, "before") + .display(); + } + // Change to PrismObjectDefinitionAsserter later protected PrismContainerDefinitionAsserter assertObjectDefinition(PrismObjectDefinition objectDef) { return assertContainerDefinition(objectDef); diff --git a/model/pom.xml b/model/pom.xml index 39f254dc5a0..e2e518b4ce4 100644 --- a/model/pom.xml +++ b/model/pom.xml @@ -35,5 +35,7 @@ report-impl certification-api certification-impl + + rest-impl diff --git a/model/report-api/src/main/java/com/evolveum/midpoint/report/api/ReportPort.java b/model/report-api/src/main/java/com/evolveum/midpoint/report/api/ReportPort.java deleted file mode 100644 index 92b7df69d67..00000000000 --- a/model/report-api/src/main/java/com/evolveum/midpoint/report/api/ReportPort.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.report.api; - -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.schema.constants.SchemaConstants; - -public interface ReportPort { - String CLASS_NAME_WITH_DOT = ReportPort.class.getName() + "."; - String PROCESS_REPORT = CLASS_NAME_WITH_DOT + "processReport"; - - QName PARSE_QUERY_RESPONSE = new QName(SchemaConstants.NS_REPORT_WS, "parseQueryResponse"); - QName PROCESS_REPORT_RESPONSE = new QName(SchemaConstants.NS_REPORT_WS, "processReportResponse"); - QName EVALUATE_SCRIPT_RESPONSE = new QName(SchemaConstants.NS_REPORT_WS, "evaluateScriptResponse"); - QName EVALUATE_AUDIT_SCRIPT_RESPONSE = new QName(SchemaConstants.NS_REPORT_WS, "evaluateAuditScriptResponse"); - QName SEARCH_OBJECTS_RESPONSE = new QName(SchemaConstants.NS_REPORT_WS, "searchObjectsResponse"); - QName GET_FIELD_VALUE_RESPONSE = new QName(SchemaConstants.NS_REPORT_WS, "getFieldValueResponse"); -} diff --git a/model/report-impl/pom.xml b/model/report-impl/pom.xml index 6980d5cfafc..f184371fb24 100644 --- a/model/report-impl/pom.xml +++ b/model/report-impl/pom.xml @@ -152,14 +152,6 @@ javax.annotation javax.annotation-api - - javax.xml.ws - jaxws-api - - - javax.xml.soap - javax.xml.soap-api - diff --git a/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/MidPointQueryExecutor.java b/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/MidPointQueryExecutor.java index 4f5dfc0bf53..7dd8ee72332 100644 --- a/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/MidPointQueryExecutor.java +++ b/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/MidPointQueryExecutor.java @@ -1,203 +1,203 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.report.impl; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; - -import com.evolveum.midpoint.prism.*; -import net.sf.jasperreports.engine.JRDataSource; -import net.sf.jasperreports.engine.JRDataset; -import net.sf.jasperreports.engine.JRException; -import net.sf.jasperreports.engine.JRParameter; -import net.sf.jasperreports.engine.JRValueParameter; -import net.sf.jasperreports.engine.JasperReportsContext; -import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource; -import net.sf.jasperreports.engine.query.JRAbstractQueryExecuter; - -import org.apache.commons.lang.StringUtils; - -import com.evolveum.midpoint.audit.api.AuditEventRecord; -import com.evolveum.midpoint.schema.GetOperationOptions; -import com.evolveum.midpoint.schema.SelectorOptions; -import com.evolveum.midpoint.schema.expression.TypedValue; -import com.evolveum.midpoint.schema.expression.VariablesMap; -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.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SecurityViolationException; -import com.evolveum.midpoint.util.exception.SystemException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.audit_3.AuditEventRecordType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; - -public abstract class MidPointQueryExecutor extends JRAbstractQueryExecuter { - - private static final Trace LOGGER = TraceManager.getTrace(MidPointLocalQueryExecutor.class); - - private Object query; - private String script; - private Class type; - - public String getScript() { - return script; - } - public Object getQuery() { - return query; - } - public Class getType() { - return type; - } - - protected abstract TypedValue createTypedPropertyValue(T realValue, Class valueClass); - - protected VariablesMap getParameters(){ - JRParameter[] params = dataset.getParameters(); - VariablesMap expressionParameters = new VariablesMap(); - for (JRParameter param : params){ - if (param.isSystemDefined()){ - continue; - } - //LOGGER.trace(((JRBaseParameter)param).getName()); - Object v = getParameterValue(param.getName()); - try{ - expressionParameters.put(param.getName(), createTypedPropertyValue(v, (Class)param.getValueClass())); - } catch (Exception e){ - //just skip properties that are not important for midpoint - } - - LOGGER.trace("p.val: {}", v); - } - return expressionParameters; - } - - protected VariablesMap getPromptingParameters() { - JRParameter[] params = dataset.getParameters(); - VariablesMap expressionParameters = new VariablesMap(); - for (JRParameter param : params) { - if (param.isSystemDefined()) { - continue; - } - if (!param.isForPrompting()) { - continue; - } - //LOGGER.trace(((JRBaseParameter)param).getName()); - Object v = getParameterValue(param.getName()); - try{ - expressionParameters.put(param.getName(), createTypedPropertyValue(v, (Class)param.getValueClass())); - } catch (Exception e){ - //just skip properties that are not important for midpoint - } - - LOGGER.trace("p.val: {}", v); - } - return expressionParameters; - } - - protected abstract Object getParsedQuery(String query, VariablesMap expressionParameters) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException; - - protected String getParsedScript(String script){ - String normalized = script.replace("", ""); - return normalized.replace("", ""); - } - - protected MidPointQueryExecutor(JasperReportsContext jasperReportsContext, JRDataset dataset, - Map parametersMap) { - super(jasperReportsContext, dataset, parametersMap); - } - - protected abstract Collection> searchObjects(Object query, Collection> options) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException; - - protected abstract Collection> evaluateScript(String script, VariablesMap parameters) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException; - - protected abstract Collection searchAuditRecords(String script, VariablesMap parameters) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException; - - protected abstract JRDataSource createDataSourceFromObjects(Collection> results); - - protected abstract JRDataSource createDataSourceFromContainerValues(Collection> results); - - @Override - protected void parseQuery() { - try { - - String s = dataset.getQuery().getText(); - LOGGER.trace("query: " + s); - if (StringUtils.isEmpty(s)) { - query = null; - } else { - if (s.startsWith("> results; - results = (Collection) searchObjects(query, SelectorOptions.createCollection(GetOperationOptions.createRaw())); - return createDataSourceFromObjects(results); - } else { - if (isAuditReport()) { - Collection audtiEventRecords = searchAuditRecords(script, getPromptingParameters()); - Collection auditEventRecordsType = new ArrayList<>(); - for (AuditEventRecord aer : audtiEventRecords){ - AuditEventRecordType aerType = aer.createAuditEventRecordType(true); - auditEventRecordsType.add(aerType); - } - return new JRBeanCollectionDataSource(auditEventRecordsType); - } else { - Collection> results; - results = evaluateScript(script, getParameters()); - return createDataSourceFromContainerValues(results); - } - } - } catch (SchemaException | ObjectNotFoundException | SecurityViolationException - | CommunicationException | ConfigurationException | ExpressionEvaluationException e) { - // TODO Auto-generated catch block - throw new JRException(e); - } - } - - protected abstract boolean isAuditReport(); - - @Override - public void close() { -// throw new UnsupportedOperationException("QueryExecutor.close() not supported"); - //nothing to DO - } - - @Override - public boolean cancelQuery() throws JRException { - throw new UnsupportedOperationException("QueryExecutor.cancelQuery() not supported"); - } - - @Override - protected String getParameterReplacement(String parameterName) { - throw new UnsupportedOperationException("QueryExecutor.getParameterReplacement() not supported"); - } - - - -} +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.report.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +import com.evolveum.midpoint.prism.*; +import net.sf.jasperreports.engine.JRDataSource; +import net.sf.jasperreports.engine.JRDataset; +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JRParameter; +import net.sf.jasperreports.engine.JRValueParameter; +import net.sf.jasperreports.engine.JasperReportsContext; +import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource; +import net.sf.jasperreports.engine.query.JRAbstractQueryExecuter; + +import org.apache.commons.lang.StringUtils; + +import com.evolveum.midpoint.audit.api.AuditEventRecord; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.schema.expression.TypedValue; +import com.evolveum.midpoint.schema.expression.VariablesMap; +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.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.exception.SecurityViolationException; +import com.evolveum.midpoint.util.exception.SystemException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.audit_3.AuditEventRecordType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; + +public abstract class MidPointQueryExecutor extends JRAbstractQueryExecuter { + + private static final Trace LOGGER = TraceManager.getTrace(MidPointLocalQueryExecutor.class); + + private Object query; + private String script; + private Class type; + + public String getScript() { + return script; + } + public Object getQuery() { + return query; + } + public Class getType() { + return type; + } + + protected abstract TypedValue createTypedPropertyValue(T realValue, Class valueClass); + + protected VariablesMap getParameters(){ + JRParameter[] params = dataset.getParameters(); + VariablesMap expressionParameters = new VariablesMap(); + for (JRParameter param : params){ + if (param.isSystemDefined()){ + continue; + } + //LOGGER.trace(((JRBaseParameter)param).getName()); + Object v = getParameterValue(param.getName()); + try{ + expressionParameters.put(param.getName(), createTypedPropertyValue(v, (Class)param.getValueClass())); + } catch (Exception e){ + //just skip properties that are not important for midpoint + } + + LOGGER.trace("p.val: {}", v); + } + return expressionParameters; + } + + protected VariablesMap getPromptingParameters() { + JRParameter[] params = dataset.getParameters(); + VariablesMap expressionParameters = new VariablesMap(); + for (JRParameter param : params) { + if (param.isSystemDefined()) { + continue; + } + if (!param.isForPrompting()) { + continue; + } + //LOGGER.trace(((JRBaseParameter)param).getName()); + Object v = getParameterValue(param.getName()); + try{ + expressionParameters.put(param.getName(), createTypedPropertyValue(v, (Class)param.getValueClass())); + } catch (Exception e){ + //just skip properties that are not important for midpoint + } + + LOGGER.trace("p.val: {}", v); + } + return expressionParameters; + } + + protected abstract Object getParsedQuery(String query, VariablesMap expressionParameters) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException; + + protected String getParsedScript(String script){ + String normalized = script.replace("", ""); + return normalized.replace("", ""); + } + + protected MidPointQueryExecutor(JasperReportsContext jasperReportsContext, JRDataset dataset, + Map parametersMap) { + super(jasperReportsContext, dataset, parametersMap); + } + + protected abstract Collection> searchObjects(Object query, Collection> options) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException; + + protected abstract Collection> evaluateScript(String script, VariablesMap parameters) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException; + + protected abstract Collection searchAuditRecords(String script, VariablesMap parameters) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException; + + protected abstract JRDataSource createDataSourceFromObjects(Collection> results); + + protected abstract JRDataSource createDataSourceFromContainerValues(Collection> results); + + @Override + protected void parseQuery() { + try { + + String s = dataset.getQuery().getText(); + LOGGER.trace("query: " + s); + if (StringUtils.isEmpty(s)) { + query = null; + } else { + if (s.startsWith("> results; + results = (Collection) searchObjects(query, SelectorOptions.createCollection(GetOperationOptions.createRaw())); + return createDataSourceFromObjects(results); + } else { + if (isAuditReport()) { + Collection auditEventRecords = searchAuditRecords(script, getPromptingParameters()); + Collection auditEventRecordsType = new ArrayList<>(); + for (AuditEventRecord aer : auditEventRecords) { + AuditEventRecordType aerType = aer.createAuditEventRecordType(true); + auditEventRecordsType.add(aerType); + } + return new JRBeanCollectionDataSource(auditEventRecordsType); + } else { + Collection> results; + results = evaluateScript(script, getParameters()); + return createDataSourceFromContainerValues(results); + } + } + } catch (SchemaException | ObjectNotFoundException | SecurityViolationException + | CommunicationException | ConfigurationException | ExpressionEvaluationException e) { + // TODO Auto-generated catch block + throw new JRException(e); + } + } + + protected abstract boolean isAuditReport(); + + @Override + public void close() { +// throw new UnsupportedOperationException("QueryExecutor.close() not supported"); + //nothing to DO + } + + @Override + public boolean cancelQuery() throws JRException { + throw new UnsupportedOperationException("QueryExecutor.cancelQuery() not supported"); + } + + @Override + protected String getParameterReplacement(String parameterName) { + throw new UnsupportedOperationException("QueryExecutor.getParameterReplacement() not supported"); + } + + + +} diff --git a/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportWebService.java b/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportWebService.java deleted file mode 100644 index 7e7650053a0..00000000000 --- a/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportWebService.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.report.impl; - -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.ResourceBundle; -import java.util.logging.Logger; - -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.xml.ns._public.common.common_3.SelectorQualifiedGetOptionsType; - -import org.apache.commons.lang3.StringUtils; -import org.apache.cxf.interceptor.Fault; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import com.evolveum.midpoint.audit.api.AuditEventRecord; -import com.evolveum.midpoint.model.api.ModelAuthorizationAction; -import com.evolveum.midpoint.model.common.util.AbstractModelWebService; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.report.api.ReportPort; -import com.evolveum.midpoint.report.api.ReportService; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.expression.VariablesMap; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.util.MiscSchemaUtil; -import com.evolveum.midpoint.security.enforcer.api.AuthorizationParameters; -import com.evolveum.midpoint.security.enforcer.api.SecurityEnforcer; -import com.evolveum.midpoint.task.api.Task; -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.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SecurityViolationException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectListType; -import com.evolveum.midpoint.xml.ns._public.common.audit_3.AuditEventRecordListType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ReportParameterType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ReportType; -import com.evolveum.midpoint.xml.ns._public.report.report_3.RemoteReportParameterType; -import com.evolveum.midpoint.xml.ns._public.report.report_3.RemoteReportParametersType; -import com.evolveum.midpoint.xml.ns._public.report.report_3.ReportPortType; - -@Service -public class ReportWebService extends AbstractModelWebService implements ReportPortType, ReportPort { - - private static final String OP_EVALUATE_SCRIPT = ReportWebService.class.getName() + ".evaluateScript"; - private static final String OP_EVALUATE_AUDIT_SCRIPT = ReportWebService.class.getName() + ".evaluateAuditScript"; - private static final String OP_PROCESS_REPORT = ReportWebService.class.getName() + ".processReport"; - - private static final Trace LOGGER = TraceManager.getTrace(ReportWebService.class); - - @Autowired private PrismContext prismContext; - @Autowired private ReportService reportService; - - @Override - public ObjectListType evaluateScript(String reportOid, String script, RemoteReportParametersType parameters) { - - Task task = createTaskInstance(OP_EVALUATE_SCRIPT); - auditLogin(task); - OperationResult operationResult = task.getResult(); - - try { - - PrismObject report = authorizeReportProcessing("evaluateScript", reportOid, task, operationResult); - - VariablesMap params = getParamsMap(parameters); - Collection resultList = reportService.evaluateScript(report, script, params, task, operationResult); - return createObjectListType(resultList); - } catch (Throwable e) { - throw new Fault(e); - } - - } - - @Override - public AuditEventRecordListType evaluateAuditScript(String reportOid, String script, RemoteReportParametersType parameters) { - - Task task = createTaskInstance(OP_EVALUATE_AUDIT_SCRIPT); - auditLogin(task); - OperationResult operationResult = task.getResult(); - - try { - PrismObject report = authorizeReportProcessing("evaluateAuditScript", reportOid, task, operationResult); - - VariablesMap params = getParamsMap(parameters); - Collection resultList = reportService.evaluateAuditScript(report, script, params, task, operationResult); - return createAuditEventRecordListType(resultList); - } catch (Throwable e) { - // TODO Auto-generated catch block - throw new Fault(e); - } - - } - - private VariablesMap getParamsMap(RemoteReportParametersType parametersType) throws SchemaException { - - prismContext.adopt(parametersType); - VariablesMap parametersMap = new VariablesMap(); - if (parametersType == null || parametersType.getRemoteParameter() == null - || parametersType.getRemoteParameter().isEmpty()) { - return parametersMap; - } - List items = parametersType.getRemoteParameter(); - for (RemoteReportParameterType item : items) { - String paramName = item.getParameterName(); - ReportParameterType param = item.getParameterValue(); - if (param == null){ - parametersMap.put(paramName, null); - continue; - } - if (param.getAny().size() == 1) { - parametersMap.put(paramName, param.getAny().get(0), param.getAny().get(0).getClass()); - } else { - parametersMap.put(paramName, param.getAny(), List.class); - } - - } - - return parametersMap; - - - } - - private ObjectListType createObjectListType(Collection resultList) { - if (resultList == null) { - return new ObjectListType(); - } - - ObjectListType results = new ObjectListType(); - int skipped = 0; - for (Object object : resultList) { - if (object instanceof PrismObject) { - results.getObject().add(((PrismObject) object).asObjectable()); - } else if (object instanceof ObjectType) { - results.getObject().add((ObjectType) object); - } else { - skipped++; - } - } - if (skipped > 0) { - LOGGER.warn("{} non-PrismObject data objects not returned, as these are not supported by ReportWebService yet", skipped); - } - - return results; - } - - private AuditEventRecordListType createAuditEventRecordListType(Collection resultList) { - if (resultList == null) { - return new AuditEventRecordListType(); - } - - AuditEventRecordListType results = new AuditEventRecordListType(); - for (AuditEventRecord auditRecord : resultList) { - results.getObject().add(auditRecord.createAuditEventRecordType(true)); - } - - return results; - } - - - @Override - public ObjectListType processReport(String reportOid, String query, RemoteReportParametersType parameters, SelectorQualifiedGetOptionsType options) { - - Task task = createTaskInstance(OP_PROCESS_REPORT); - auditLogin(task); - OperationResult operationResult = task.getResult(); - - try { - - PrismObject report = authorizeReportProcessing("processReport", reportOid, task, operationResult); - - VariablesMap parametersMap = getParamsMap(parameters); - ObjectQuery q = reportService.parseQuery(report, query, parametersMap, task, operationResult); - Collection> resultList = (Collection) reportService.searchObjects(q, - MiscSchemaUtil.optionsTypeToOptions(options, prismContext), task, operationResult); - - return createObjectListType(resultList); - } catch (SchemaException | ObjectNotFoundException | SecurityViolationException - | CommunicationException | ConfigurationException | ExpressionEvaluationException e) { - // TODO Auto-generated catch block - throw new Fault(e); - } - - } - - private PrismObject authorizeReportProcessing(String operationName, String reportOid, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { - if (StringUtils.isBlank(reportOid)) { - LOGGER.error("No report OID was specified during access to report service operation {}", operationName); - throw new SchemaException("No report OID specified"); - } - PrismObject report = reportService.getReportDefinition(reportOid, task, result); - if (!reportService.isAuthorizedToRunReport(report, task, result)) { - LOGGER.error("User is not authorized to run report {}, therefore access to report service operation {} was denied", report, operationName); - throw new Fault(new SecurityViolationException("Not authorized")); - } - return report; - } - -} diff --git a/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportWebServiceRaw.java b/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportWebServiceRaw.java deleted file mode 100644 index 90a2c7bbf7a..00000000000 --- a/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportWebServiceRaw.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.report.impl; - -import java.io.PrintWriter; -import java.io.StringWriter; - -import javax.xml.namespace.QName; -import javax.xml.soap.Detail; -import javax.xml.soap.SOAPException; -import javax.xml.soap.SOAPFactory; -import javax.xml.soap.SOAPFault; -import javax.xml.transform.dom.DOMSource; -import javax.xml.ws.Holder; -import javax.xml.ws.Provider; -import javax.xml.ws.soap.SOAPFaultException; - -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.SerializationContext; -import com.evolveum.midpoint.prism.SerializationOptions; -import com.evolveum.midpoint.report.api.ReportPort; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectListType; -import com.evolveum.midpoint.xml.ns._public.common.audit_3.AuditEventRecordListType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultType; -import com.evolveum.midpoint.xml.ns._public.common.fault_3.FaultMessage; -import com.evolveum.midpoint.xml.ns._public.report.report_3.EvaluateAuditScriptResponseType; -import com.evolveum.midpoint.xml.ns._public.report.report_3.EvaluateAuditScriptType; -import com.evolveum.midpoint.xml.ns._public.report.report_3.EvaluateScriptResponseType; -import com.evolveum.midpoint.xml.ns._public.report.report_3.EvaluateScriptType; -import com.evolveum.midpoint.xml.ns._public.report.report_3.ProcessReportResponseType; -import com.evolveum.midpoint.xml.ns._public.report.report_3.ProcessReportType; - -@Service -public class ReportWebServiceRaw implements Provider { - - private static final Trace LOGGER = TraceManager.getTrace(ReportWebService.class); - - public static final String NS_SOAP11_ENV = "http://schemas.xmlsoap.org/soap/envelope/"; - public static final String NS_SOAP11_ENV_PREFIX = "SOAP-ENV"; - public static final QName SOAP11_FAULT = new QName(NS_SOAP11_ENV, "Fault"); - public static final QName SOAP11_FAULTCODE = new QName("", "faultcode"); - public static final String SOAP11_FAULTCODE_SERVER = NS_SOAP11_ENV_PREFIX + ":Server"; - public static final QName SOAP11_FAULTSTRING = new QName("", "faultstring"); - public static final QName SOAP11_FAULTACTOR = new QName("", "faultactor"); - public static final QName SOAP11_FAULT_DETAIL = new QName("", "detail"); - public static final String ACTOR = "TODO"; - - @Autowired(required = true) - private PrismContext prismContext; - - @Autowired(required = true) - private ReportWebService reportService; - - @Override - public DOMSource invoke(DOMSource request) { - try { - return invokeAllowingFaults(request); - } catch (FaultMessage faultMessage) { - try { - SOAPFactory factory = SOAPFactory.newInstance(); - SOAPFault soapFault = factory.createFault(); - soapFault.setFaultCode(SOAP11_FAULTCODE_SERVER); // todo here is a constant until we have a mechanism to determine the correct value (client / server) - soapFault.setFaultString(faultMessage.getMessage()); - Detail detail = soapFault.addDetail(); - serializeFaultMessage(detail, faultMessage); - // fault actor? - // stack trace of the outer exception (FaultMessage) is unimportant, because it is always created at one place - // todo consider providing stack trace of the inner exception - //Detail detail = soapFault.addDetail(); - //detail.setTextContent(getStackTraceAsString(faultMessage)); - throw new SOAPFaultException(soapFault); - } catch (SOAPException e) { - throw new RuntimeException("SOAP Exception: " + e.getMessage(), e); - } - } - } - - public DOMSource invokeAllowingFaults(DOMSource request) throws FaultMessage { - Node rootNode = request.getNode(); - Element rootElement; - if (rootNode instanceof Document) { - rootElement = ((Document) rootNode).getDocumentElement(); - } else if (rootNode instanceof Element) { - rootElement = (Element) rootNode; - } else { -// throw ws.createIllegalArgumentFault("Unexpected DOM node type: " + rootNode); - throw new FaultMessage("Unexpected DOM node type: " + rootNode); - } - - Object requestObject; - try { - requestObject = prismContext.parserFor(rootElement).parseRealValue(); - } catch (SchemaException e) { - throw new FaultMessage("Couldn't parse SOAP request body because of schema exception: " + e.getMessage()); -// throw ws.createIllegalArgumentFault("Couldn't parse SOAP request body because of schema exception: " + e.getMessage()); - } - - Node response; - Holder operationResultTypeHolder = new Holder<>(); - SerializationContext ctx= new SerializationContext(SerializationOptions.createSerializeReferenceNames()); - try { - if (requestObject instanceof EvaluateScriptType){ - EvaluateScriptType s = (EvaluateScriptType) requestObject; - ObjectListType olt = reportService.evaluateScript(s.getReportOid(), s.getScript(), s.getParameters()); - EvaluateScriptResponseType sr = new EvaluateScriptResponseType(); - sr.setObjectList(olt); - response = prismContext.domSerializer().context(ctx).serializeAnyData(sr, ReportPort.EVALUATE_SCRIPT_RESPONSE); - } else if (requestObject instanceof EvaluateAuditScriptType){ - EvaluateAuditScriptType s = (EvaluateAuditScriptType) requestObject; - AuditEventRecordListType olt = reportService.evaluateAuditScript(s.getReportOid(), s.getScript(), s.getParameters()); - EvaluateAuditScriptResponseType sr = new EvaluateAuditScriptResponseType(); - sr.setObjectList(olt); - response = prismContext.domSerializer().context(ctx).serializeAnyData(sr, ReportPort.EVALUATE_AUDIT_SCRIPT_RESPONSE); - } else if (requestObject instanceof ProcessReportType){ - ProcessReportType p = (ProcessReportType) requestObject; - ObjectListType olt = reportService.processReport(p.getReportOid(), p.getQuery(), p.getParameters(), p.getOptions()); - ProcessReportResponseType pr = new ProcessReportResponseType(); - pr.setObjectList(olt); - response = prismContext.domSerializer().context(ctx).serializeAnyData(pr, ReportPort.PROCESS_REPORT_RESPONSE); - } else { - throw new FaultMessage("Unsupported request type: " + requestObject); - } - } catch (SchemaException e) { - throwFault(e, operationResultTypeHolder.value); - // not reached - return null; - } - - // brutal hack for MID-2001 (serializing and parsing eliminates the problem!) - //String serialized = DOMUtil.printDom(response).toString(); - //LOGGER.trace("WEB SERVICE RESPONSE:\n{}", serialized); - //response = DOMUtil.parseDocument(serialized); - - return new DOMSource(response); - } - - private void serializeFaultMessage(Detail detail, FaultMessage faultMessage) { - prismContext.hacks() - .serializeFaultMessage(detail, faultMessage.getFaultInfo(), SchemaConstants.FAULT_MESSAGE_ELEMENT_NAME, LOGGER); - } - - private String getStackTraceAsString(FaultMessage faultMessage) { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - faultMessage.printStackTrace(pw); - pw.close(); - return sw.toString(); - } - - private void throwFault(Exception ex, OperationResultType resultType) throws FaultMessage { - if (resultType != null) { - throw new FaultMessage(ex.getMessage()); -// ws.throwFault(ex, OperationResult.createOperationResult(resultType)); - } else { - throw new FaultMessage(ex.getMessage()); -// ws.throwFault(ex, null); - } - } - -} diff --git a/model/report-impl/src/main/resources/ctx-report.xml b/model/report-impl/src/main/resources/ctx-report.xml index fdd004babe2..698f46528c4 100644 --- a/model/report-impl/src/main/resources/ctx-report.xml +++ b/model/report-impl/src/main/resources/ctx-report.xml @@ -7,44 +7,15 @@ --> + default-lazy-init="false"> - - + + - - - - - - - - - - - - - - - - - - diff --git a/model/report-impl/src/test/java/com/evolveum/midpoint/report/TestReportWebService.java b/model/report-impl/src/test/java/com/evolveum/midpoint/report/TestReportWebService.java deleted file mode 100644 index b2a8ee7e7e2..00000000000 --- a/model/report-impl/src/test/java/com/evolveum/midpoint/report/TestReportWebService.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.report; - -import static org.testng.AssertJUnit.assertEquals; -import static org.testng.AssertJUnit.assertNotNull; - -import org.apache.cxf.interceptor.Fault; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.annotation.DirtiesContext.ClassMode; -import org.springframework.test.context.ContextConfiguration; -import org.testng.annotations.Test; - -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.report.impl.ReportWebService; -import com.evolveum.midpoint.schema.SearchResultList; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.*; -import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectListType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ReportType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -import com.evolveum.midpoint.xml.ns._public.report.report_3.RemoteReportParametersType; - -/** - * Basic report tests. - */ -@ContextConfiguration(locations = { "classpath:ctx-report-test-main.xml" }) -@DirtiesContext(classMode = ClassMode.AFTER_CLASS) -public class TestReportWebService extends AbstractReportIntegrationTest { - - @Autowired protected ReportWebService reportWebService; - - @Override - public void initSystem(Task initTask, OperationResult initResult) throws Exception { - super.initSystem(initTask, initResult); - - repoAddObjectFromFile(ROLE_READER_FILE, true, initResult); - repoAddObjectFromFile(USER_READER_FILE, true, initResult); - repoAddObjectFromFile(ROLE_RUNNER_FILE, true, initResult); - repoAddObjectFromFile(USER_RUNNER_FILE, true, initResult); - repoAddObjectFromFile(USER_READER_RUNNER_FILE, true, initResult); - - repoAddObjectFromFile(REPORT_USER_LIST_EXPRESSIONS_CSV_FILE, ReportType.class, initResult); - repoAddObjectFromFile(REPORT_USER_LIST_EXPRESSIONS_POISONOUS_QUERY_CSV_FILE, ReportType.class, initResult); - repoAddObjectFromFile(REPORT_USER_LIST_EXPRESSIONS_POISONOUS_FIELD_CSV_FILE, ReportType.class, initResult); - - // Let's make this more interesting by adding a couple of users - importObjectsFromFileNotRaw(USERS_MONKEY_ISLAND_FILE, initTask, initResult); - } - - @Test - public void test000Sanity() { - assertNotNull("No web service", reportWebService); - } - - @Test - public void test100ProcessReportUserList() throws Exception { - String query = createAllQueryString(UserType.class); - RemoteReportParametersType parameters = createReportParameters(); - - // WHEN - when(); - ObjectListType userList = reportWebService.processReport(REPORT_USER_LIST_EXPRESSIONS_CSV_OID, query, parameters, null); - - // THEN - then(); - displayValue("Returned user list (" + userList.getObject().size() + " objects)", userList); - - assertUserList(userList); - } - - @Test - public void test110ProcessReportUserListNoReportOid() { - String query = createAllQueryString(UserType.class); - RemoteReportParametersType parameters = createReportParameters(); - - try { - - // WHEN - when(); - reportWebService.processReport(null, query, parameters, null); - - assertNotReached(); - - } catch (Fault f) { - // THEN - then(); - displayException("Expected fault", f); - } - } - - @Test - public void test112ProcessReportUserListInvalidReportOid() { - String query = createAllQueryString(UserType.class); - RemoteReportParametersType parameters = createReportParameters(); - - try { - - // WHEN - when(); - reportWebService.processReport("l00n3y", query, parameters, null); - - assertNotReached(); - - } catch (Fault f) { - // THEN - then(); - displayException("Expected fault", f); - } - } - - /** - * MID-5463 - */ - @Test - public void test115ProcessReportUserListUnauthorizedReader() throws Exception { - login(USER_READER_USERNAME); - - String query = createAllQueryString(UserType.class); - RemoteReportParametersType parameters = createReportParameters(); - - try { - - // WHEN - when(); - reportWebService.processReport(REPORT_USER_LIST_EXPRESSIONS_CSV_OID, query, parameters, null); - - assertNotReached(); - - } catch (Fault f) { - // THEN - then(); - displayException("Expected fault", f); - } finally { - login(USER_ADMINISTRATOR_USERNAME); - } - } - - /** - * MID-5463 - */ - @Test - public void test116ProcessReportUserListUnauthorizedRunner() throws Exception { - login(USER_RUNNER_USERNAME); - - String query = createAllQueryString(UserType.class); - RemoteReportParametersType parameters = createReportParameters(); - - try { - - // WHEN - when(); - reportWebService.processReport(REPORT_USER_LIST_EXPRESSIONS_CSV_OID, query, parameters, null); - - assertNotReached(); - - } catch (Fault f) { - // THEN - then(); - displayException("Expected fault", f); - } finally { - login(USER_ADMINISTRATOR_USERNAME); - } - } - - /** - * MID-5463 - */ - @Test - public void test119ProcessReportUserListReaderRunner() throws Exception { - login(USER_READER_RUNNER_USERNAME); - - String query = createAllQueryString(UserType.class); - RemoteReportParametersType parameters = createReportParameters(); - - ObjectListType userList; - try { - - // WHEN - when(); - userList = reportWebService.processReport(REPORT_USER_LIST_EXPRESSIONS_CSV_OID, query, parameters, null); - - } finally { - login(USER_ADMINISTRATOR_USERNAME); - } - - // THEN - then(); - displayValue("Returned user list (" + userList.getObject().size() + " objects)", userList); - - assertUserList(userList); - } - - // TODO: test that violates safe profile - - private String createAllQueryString(Class type) { - return "" + type.getSimpleName() + ""; - } - - private RemoteReportParametersType createReportParameters() { - return new RemoteReportParametersType(); - } - - private void assertUserList(ObjectListType userList) throws SchemaException, ObjectNotFoundException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException { - Task task = getTestTask(); - OperationResult result = task.getResult(); - SearchResultList> currentUsers = modelService.searchObjects(UserType.class, null, null, task, result); - displayValue("Current users in midPoint (" + currentUsers.size() + " users)", currentUsers.toString()); - - assertEquals("Unexpected number of returned objects", currentUsers.size(), userList.getObject().size()); - } - -} diff --git a/model/report-impl/src/test/java/com/evolveum/midpoint/report/TestReportWebServiceSafe.java b/model/report-impl/src/test/java/com/evolveum/midpoint/report/TestReportWebServiceSafe.java deleted file mode 100644 index 0fb55a83e57..00000000000 --- a/model/report-impl/src/test/java/com/evolveum/midpoint/report/TestReportWebServiceSafe.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.report; - -import java.io.File; - -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.annotation.DirtiesContext.ClassMode; -import org.springframework.test.context.ContextConfiguration; - -/** - * Basic report tests. - */ -@ContextConfiguration(locations = { "classpath:ctx-report-test-main.xml" }) -@DirtiesContext(classMode = ClassMode.AFTER_CLASS) -public class TestReportWebServiceSafe extends TestReportWebService { - - @Override - protected File getSystemConfigurationFile() { - return SYSTEM_CONFIGURATION_SAFE_FILE; - } - -} diff --git a/model/report-impl/src/test/resources/ctx-report-test-main.xml b/model/report-impl/src/test/resources/ctx-report-test-main.xml index a861a824175..af931d1b9d8 100644 --- a/model/report-impl/src/test/resources/ctx-report-test-main.xml +++ b/model/report-impl/src/test/resources/ctx-report-test-main.xml @@ -8,24 +8,11 @@ --> + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" + default-lazy-init="false" default-autowire="byName"> - + @@ -38,7 +25,5 @@ - - diff --git a/model/report-impl/testng-integration.xml b/model/report-impl/testng-integration.xml index 611433639be..1710ba2421c 100644 --- a/model/report-impl/testng-integration.xml +++ b/model/report-impl/testng-integration.xml @@ -12,8 +12,6 @@ - - diff --git a/model/rest-impl/pom.xml b/model/rest-impl/pom.xml new file mode 100644 index 00000000000..45ace4e84c2 --- /dev/null +++ b/model/rest-impl/pom.xml @@ -0,0 +1,92 @@ + + + + + 4.0.0 + + + model + com.evolveum.midpoint.model + 4.2-SNAPSHOT + + + rest-impl + + midPoint REST-ish service implementation + + + true + + + + + com.evolveum.midpoint.model + model-impl + ${project.version} + + + com.evolveum.midpoint.infra + prism-api + ${project.version} + + + com.evolveum.midpoint.repo + task-api + ${project.version} + + + com.evolveum.midpoint.repo + security-api + ${project.version} + + + com.evolveum.midpoint.infra + schema + ${project.version} + + + com.evolveum.midpoint.infra + util + ${project.version} + + + + org.springframework + spring-web + + + org.springframework + spring-webmvc + + + org.springframework + spring-beans + + + org.springframework + spring-context + + + javax.servlet + javax.servlet-api + + + + org.jetbrains + annotations + + + commons-collections + commons-collections + + + org.apache.commons + commons-lang3 + + + diff --git a/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/AbstractRestController.java b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/AbstractRestController.java new file mode 100644 index 00000000000..ffa7b887e61 --- /dev/null +++ b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/AbstractRestController.java @@ -0,0 +1,153 @@ +package com.evolveum.midpoint.rest.impl; + +import static org.springframework.http.ResponseEntity.status; + +import java.net.URI; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import com.evolveum.midpoint.model.impl.ModelRestService; +import com.evolveum.midpoint.model.impl.security.SecurityHelper; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.security.api.ConnectionEnvironment; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.task.api.TaskManager; +import com.evolveum.midpoint.util.exception.*; +import com.evolveum.midpoint.util.logging.LoggingUtils; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultType; + +/** + * Base REST controller class providing common (utility) methods and logger. + */ +class AbstractRestController { + + protected final Trace logger = TraceManager.getTrace(getClass()); + private final String opNamePrefix = getClass().getName() + "."; + + @Autowired protected SecurityHelper securityHelper; + @Autowired protected TaskManager taskManager; + + protected Task initRequest() { + // No need to audit login. it was already audited during authentication + Task task = taskManager.createTaskInstance(ModelRestService.OPERATION_REST_SERVICE); + task.setChannel(SchemaConstants.CHANNEL_REST_URI); + return task; + } + + protected OperationResult createSubresult(Task task, String operation) { + return task.getResult().createSubresult(opNamePrefix + operation); + } + + protected ResponseEntity createResponse(HttpStatus statusCode, OperationResult result) { + return createResponse(statusCode, null, result, false); + } + + protected ResponseEntity createResponse( + HttpStatus httpStatus, T body, OperationResult result) { + return createResponse(httpStatus, body, result, false); + } + + protected ResponseEntity createResponse(HttpStatus httpStatus, + T body, OperationResult result, boolean sendOriginObjectIfNotSuccess) { + result.computeStatusIfUnknown(); + + if (result.isPartialError()) { + return createBody(status(250), sendOriginObjectIfNotSuccess, body, result); + } else if (result.isHandledError()) { + return createBody(status(240), sendOriginObjectIfNotSuccess, body, result); + } + + return status(httpStatus).body(body); + } + + protected ResponseEntity createResponseWithLocation( + HttpStatus httpStatus, URI location, OperationResult result) { + result.computeStatusIfUnknown(); + + if (result.isPartialError()) { + return ResponseEntity.status(250).location(location).body(result); + } else if (result.isHandledError()) { + return ResponseEntity.status(240).location(location).body(result); + } + + return location == null ? ResponseEntity.status(httpStatus).build() + : ResponseEntity.status(httpStatus).location(location).build(); + } + + protected ResponseEntity createBody(ResponseEntity.BodyBuilder builder, + boolean sendOriginObjectIfNotSuccess, T body, OperationResult result) { + if (sendOriginObjectIfNotSuccess) { + return builder.body(body); + } + return builder.body(result); + } + + protected ResponseEntity handleException(OperationResult result, Throwable t) { + LoggingUtils.logUnexpectedException(logger, "Got exception while servicing REST request: {}", t, + result != null ? result.getOperation() : "(null)"); + return handleExceptionNoLog(result, t); + } + + protected ResponseEntity handleExceptionNoLog(OperationResult result, Throwable t) { + return createErrorResponseBuilder(result, t); + } + + protected ResponseEntity createErrorResponseBuilder(OperationResult result, Throwable t) { + if (t instanceof ObjectNotFoundException) { + return createErrorResponseBuilder(HttpStatus.NOT_FOUND, result); + } + + if (t instanceof CommunicationException || t instanceof TunnelException) { + return createErrorResponseBuilder(HttpStatus.GATEWAY_TIMEOUT, result); + } + + if (t instanceof SecurityViolationException) { + return createErrorResponseBuilder(HttpStatus.FORBIDDEN, result); + } + + if (t instanceof ConfigurationException) { + return createErrorResponseBuilder(HttpStatus.BAD_GATEWAY, result); + } + + if (t instanceof SchemaException || t instanceof ExpressionEvaluationException) { + return createErrorResponseBuilder(HttpStatus.BAD_REQUEST, result); + } + + if (t instanceof PolicyViolationException + || t instanceof ObjectAlreadyExistsException + || t instanceof ConcurrencyException) { + return createErrorResponseBuilder(HttpStatus.CONFLICT, result); + } + + return createErrorResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR, result); + } + + protected ResponseEntity createErrorResponseBuilder( + HttpStatus status, OperationResult result) { + OperationResultType resultBean; + if (result != null) { + result.computeStatusIfUnknown(); + resultBean = result.createOperationResultType(); + } else { + resultBean = null; + } + return status(status).body(resultBean); + } + + protected void finishRequest(Task task) { + // TODO what level of auditing do we want anyway? +// if (isExperimentalEnabled()) { +// auditEvent(request); +// SecurityContextHolder.getContext().setAuthentication(null); +// } else { + task.getResult().computeStatus(); + ConnectionEnvironment connEnv = ConnectionEnvironment.create(SchemaConstants.CHANNEL_REST_URI); + connEnv.setSessionIdOverride(task.getTaskIdentifier()); + securityHelper.auditLogout(connEnv, task); + } +} diff --git a/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/ExtensionSchemaRestController.java b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/ExtensionSchemaRestController.java new file mode 100644 index 00000000000..ceb731edbd5 --- /dev/null +++ b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/ExtensionSchemaRestController.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2010-2017 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.rest.impl; + +import java.io.File; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.evolveum.midpoint.common.configuration.api.MidpointConfiguration; +import com.evolveum.midpoint.model.api.ModelAuthorizationAction; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.schema.SchemaDescription; +import com.evolveum.midpoint.prism.schema.SchemaRegistry; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.security.enforcer.api.AuthorizationParameters; +import com.evolveum.midpoint.security.enforcer.api.SecurityEnforcer; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.logging.LoggingUtils; + +@RestController +@RequestMapping(value = "/rest2/schema") +public class ExtensionSchemaRestController extends AbstractRestController { + + @Autowired private PrismContext prismContext; + @Autowired private SecurityEnforcer securityEnforcer; + + @GetMapping(produces = MediaType.TEXT_PLAIN_VALUE) + public ResponseEntity listSchemas() { + + Task task = initRequest(); + OperationResult result = createSubresult(task, "listSchemas"); + + ResponseEntity response; + try { + securityEnforcer.authorize(ModelAuthorizationAction.GET_EXTENSION_SCHEMA.getUrl(), null, AuthorizationParameters.EMPTY, null, task, result); + + SchemaRegistry registry = prismContext.getSchemaRegistry(); + Collection descriptions = registry.getSchemaDescriptions(); + + List names = new ArrayList<>(); + + for (SchemaDescription description : descriptions) { + String name = computeName(description); + if (name != null) { + names.add(name); + } + } + + String output = StringUtils.join(names, "\n"); + response = ResponseEntity.ok(output); + } catch (Exception ex) { + // we avoid RestServiceUtil.handleException because we cannot serialize OperationResultType into text/plain + LoggingUtils.logUnexpectedException(logger, "Got exception while servicing REST request: {}", ex, result.getOperation()); + response = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(ex.getMessage()); // TODO handle this somehow better + } + + finishRequest(task); + return response; + } + + private String computeName(SchemaDescription description) { + String path = description.getPath(); + if (path == null) { + return null; + } + + File file = new File(path); + if (!file.exists()) { + return null; + } + + String midpointHome = System.getProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY); + java.nio.file.Path homePath = Paths.get(midpointHome, "schema"); + java.nio.file.Path relative = homePath.relativize(file.toPath()); + + return relative.toString(); + } + + @GetMapping(value = "/{name}", + produces = { MediaType.TEXT_XML_VALUE, MediaType.TEXT_PLAIN_VALUE }) + public ResponseEntity getSchema( + @PathVariable("name") String name) { + + Task task = initRequest(); + OperationResult result = createSubresult(task, "getSchema"); + + ResponseEntity response; + try { + securityEnforcer.authorize(ModelAuthorizationAction.GET_EXTENSION_SCHEMA.getUrl(), + null, AuthorizationParameters.EMPTY, null, task, result); + + if (name == null) { + response = ResponseEntity.status(HttpStatus.BAD_REQUEST).contentType(MediaType.TEXT_PLAIN) + .body("Name not defined"); + } else if (!name.toLowerCase().endsWith(".xsd") && name.length() > 4) { + response = ResponseEntity.status(HttpStatus.BAD_REQUEST).contentType(MediaType.TEXT_PLAIN) + .body("Name must be an xsd schema (.xsd extension expected)"); + } else { + SchemaRegistry registry = prismContext.getSchemaRegistry(); + Collection descriptions = registry.getSchemaDescriptions(); + + SchemaDescription description = null; + for (SchemaDescription desc : descriptions) { + String descName = computeName(desc); + if (descName != null && descName.equals(name)) { + description = desc; + break; + } + } + + if (description != null) { + response = ResponseEntity.ok(new File(description.getPath())); + } else { + response = ResponseEntity + .status(HttpStatus.NOT_FOUND) + .contentType(MediaType.TEXT_PLAIN) + .body("Unknown name"); + } + } + } catch (Exception ex) { + result.computeStatus(); + response = handleException(result, ex); + } + + finishRequest(task); + return response; + } +} diff --git a/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/MidpointAbstractHttpMessageConverter.java b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/MidpointAbstractHttpMessageConverter.java new file mode 100644 index 00000000000..085b67c95fd --- /dev/null +++ b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/MidpointAbstractHttpMessageConverter.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2010-2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.rest.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Locale; +import java.util.function.Function; +import javax.xml.namespace.QName; + +import org.jetbrains.annotations.NotNull; +import org.springframework.http.HttpInputMessage; +import org.springframework.http.HttpOutputMessage; +import org.springframework.http.MediaType; +import org.springframework.http.converter.AbstractHttpMessageConverter; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.http.converter.HttpMessageNotWritableException; + +import com.evolveum.midpoint.common.LocalizationService; +import com.evolveum.midpoint.model.impl.scripting.ScriptingExpressionEvaluator; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.util.LocalizableMessage; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.LoggingUtils; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ExecuteScriptType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ScriptingExpressionType; + +public abstract class MidpointAbstractHttpMessageConverter extends AbstractHttpMessageConverter { + + private static final Trace LOGGER = TraceManager.getTrace(MidpointAbstractHttpMessageConverter.class); + + protected final PrismContext prismContext; + private final LocalizationService localizationService; + + protected MidpointAbstractHttpMessageConverter(PrismContext prismContext, + LocalizationService localizationService, MediaType... supportedMediaTypes) { + super(supportedMediaTypes); + this.prismContext = prismContext; + this.localizationService = localizationService; + } + + protected abstract PrismSerializer getSerializer(); + protected abstract PrismParser getParser(InputStream entityStream); + + @Override + protected boolean supports(Class clazz) { + return clazz.getName().startsWith("com.evolveum.midpoint") + || clazz.getName().startsWith("com.evolveum.prism"); + } + + @Override + protected T readInternal(@NotNull Class clazz, @NotNull HttpInputMessage inputMessage) + throws IOException, HttpMessageNotReadableException { + PrismParser parser = getParser(inputMessage.getBody()); + + Object object; + try { + if (PrismObject.class.isAssignableFrom(clazz)) { + object = parser.parse(); + } else { + object = parser.parseRealValue(); + } + + if (object != null && !clazz.isInstance(object)) { + // This code covers type migrations, eventually we'd like to drop old type support. + object = migrateType(object, clazz); + } + return clazz.cast(object); + } catch (SchemaException e) { + throw new HttpMessageNotReadableException("Failure during read", e, inputMessage); + } + } + + // this better be T after this is executed + private Object migrateType(Object object, Class clazz) { + if (clazz.equals(ExecuteScriptType.class)) { + // TODO: deprecate ScriptingExpressionType in favour of ExecuteScriptType (next LTS? 4.4? 5.0?) + if (object instanceof ExecuteScriptType) { + return object; + } else if (object instanceof ScriptingExpressionType) { + return ScriptingExpressionEvaluator.createExecuteScriptCommand((ScriptingExpressionType) object); + } else { + throw new IllegalArgumentException("Wrong input value for ExecuteScriptType: " + object); + } + } + // no other migrations + return object; + } + + @Override + protected void writeInternal(@NotNull T object, @NotNull HttpOutputMessage outputMessage) + throws IOException, HttpMessageNotWritableException { + // TODO implement in the standard serializer; also change root name + QName fakeQName = new QName(PrismConstants.NS_TYPES, "object"); + String serializedForm; + + PrismSerializer serializer = getSerializer() + .options(SerializationOptions.createSerializeReferenceNames()); + + try { + if (object instanceof ObjectType) { + ObjectType ot = (ObjectType) object; + serializedForm = serializer.serialize(ot.asPrismObject()); + } else if (object instanceof PrismObject) { + serializedForm = serializer.serialize((PrismObject) object); + } else if (object instanceof OperationResult) { + Function resolveKeys = msg -> localizationService.translate(msg, Locale.US); + OperationResultType operationResultType = ((OperationResult) object).createOperationResultType(resolveKeys); + serializedForm = serializer.serializeAnyData(operationResultType, fakeQName); + } else { + serializedForm = serializer.serializeAnyData(object, fakeQName); + } + outputMessage.getBody().write(serializedForm.getBytes(StandardCharsets.UTF_8)); + } catch (SchemaException | RuntimeException e) { + LoggingUtils.logException(LOGGER, "Couldn't marshal element to string: {}", e, object); + } + } +} diff --git a/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/MidpointJsonHttpMessageConverter.java b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/MidpointJsonHttpMessageConverter.java new file mode 100644 index 00000000000..97aab8e4f62 --- /dev/null +++ b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/MidpointJsonHttpMessageConverter.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2010-2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.rest.impl; + +import java.io.InputStream; + +import org.springframework.http.MediaType; + +import com.evolveum.midpoint.common.LocalizationService; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismParser; +import com.evolveum.midpoint.prism.PrismSerializer; + +public class MidpointJsonHttpMessageConverter extends MidpointAbstractHttpMessageConverter { + + public static final MediaType[] MEDIA_TYPES = { + MediaType.APPLICATION_JSON + }; + + protected MidpointJsonHttpMessageConverter( + PrismContext prismContext, LocalizationService localizationService) { + super(prismContext, localizationService, MEDIA_TYPES); + } + + @Override + protected PrismSerializer getSerializer() { + return prismContext.jsonSerializer(); + } + + @Override + protected PrismParser getParser(InputStream entityStream) { + return prismContext.parserFor(entityStream).json(); + } +} diff --git a/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/MidpointXmlHttpMessageConverter.java b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/MidpointXmlHttpMessageConverter.java new file mode 100644 index 00000000000..885ccda9d52 --- /dev/null +++ b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/MidpointXmlHttpMessageConverter.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2010-2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.rest.impl; + +import java.io.InputStream; + +import org.springframework.http.MediaType; + +import com.evolveum.midpoint.common.LocalizationService; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismParser; +import com.evolveum.midpoint.prism.PrismSerializer; + +public class MidpointXmlHttpMessageConverter extends MidpointAbstractHttpMessageConverter { + + public static final MediaType[] MEDIA_TYPES = { + MediaType.APPLICATION_XML, MediaType.TEXT_XML + }; + + protected MidpointXmlHttpMessageConverter( + PrismContext prismContext, LocalizationService localizationService) { + super(prismContext, localizationService, MEDIA_TYPES); + } + + @Override + protected PrismSerializer getSerializer() { + return prismContext.xmlSerializer(); + } + + @Override + protected PrismParser getParser(InputStream entityStream) { + return prismContext.parserFor(entityStream).xml(); + } +} diff --git a/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/MidpointYamlHttpMessageConverter.java b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/MidpointYamlHttpMessageConverter.java new file mode 100644 index 00000000000..6ee1b581368 --- /dev/null +++ b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/MidpointYamlHttpMessageConverter.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2010-2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.rest.impl; + +import java.io.InputStream; + +import org.springframework.http.MediaType; + +import com.evolveum.midpoint.common.LocalizationService; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismParser; +import com.evolveum.midpoint.prism.PrismSerializer; + +public class MidpointYamlHttpMessageConverter extends MidpointAbstractHttpMessageConverter { + + public static final MediaType[] MEDIA_TYPES = { + MediaType.valueOf("application/yaml"), MediaType.valueOf("text/yaml"), + MediaType.valueOf("application/yml"), MediaType.valueOf("text/yml"), + MediaType.valueOf("application/*-yaml"), MediaType.valueOf("text/*-yaml"), + MediaType.valueOf("application/*.yaml"), MediaType.valueOf("text/*.yaml") + }; + + protected MidpointYamlHttpMessageConverter( + PrismContext prismContext, LocalizationService localizationService) { + super(prismContext, localizationService, MEDIA_TYPES); + } + + @Override + protected PrismSerializer getSerializer() { + return prismContext.yamlSerializer(); + } + + @Override + protected PrismParser getParser(InputStream entityStream) { + return prismContext.parserFor(entityStream).yaml(); + } +} diff --git a/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/ModelRestController.java b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/ModelRestController.java new file mode 100644 index 00000000000..3f6e9102d21 --- /dev/null +++ b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/ModelRestController.java @@ -0,0 +1,913 @@ +package com.evolveum.midpoint.rest.impl; + +import static org.springframework.http.ResponseEntity.status; + +import java.net.URI; +import java.util.Collection; +import java.util.List; +import javax.xml.namespace.QName; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.Validate; +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import com.evolveum.midpoint.model.api.*; +import com.evolveum.midpoint.model.impl.ModelCrudService; +import com.evolveum.midpoint.model.impl.scripting.PipelineData; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.delta.ItemDelta; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.path.ItemPathCollectionsUtil; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.schema.DefinitionProcessingOption; +import com.evolveum.midpoint.schema.DeltaConvertor; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.schema.constants.MidPointConstants; +import com.evolveum.midpoint.schema.constants.ObjectTypes; +import com.evolveum.midpoint.schema.expression.VariablesMap; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.security.api.SecurityUtil; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.exception.*; +import com.evolveum.midpoint.util.logging.LoggingUtils; +import com.evolveum.midpoint.xml.ns._public.common.api_types_3.*; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ExecuteScriptOutputType; +import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ExecuteScriptType; +import com.evolveum.prism.xml.ns._public.query_3.QueryType; + +@RestController +@RequestMapping(value = ModelRestController.BASE_PATH) +public class ModelRestController extends AbstractRestController { + + public static final String BASE_PATH = "/rest2"; + public static final String GET_OBJECT_PATH = "/{type}/{id}"; + + private static final String CURRENT = "current"; + private static final long WAIT_FOR_TASK_STOP = 2000L; + + @Autowired private ModelCrudService model; + @Autowired private ModelDiagnosticService modelDiagnosticService; + @Autowired private ModelInteractionService modelInteraction; + @Autowired private ModelService modelService; + @Autowired private PrismContext prismContext; + @Autowired private ScriptingService scriptingService; + @Autowired private TaskService taskService; + + @PostMapping("/{type}/{oid}/generate") + public ResponseEntity generateValue( + @PathVariable("type") String type, + @PathVariable("oid") String oid, + @RequestBody PolicyItemsDefinitionType policyItemsDefinition) { + + Task task = initRequest(); + OperationResult parentResult = createSubresult(task, "generateValue"); + + Class clazz = ObjectTypes.getClassFromRestType(type); + + ResponseEntity response; + try { + PrismObject object = model.getObject(clazz, oid, null, task, parentResult); + response = generateValue(object, policyItemsDefinition, task, parentResult); + } catch (Exception ex) { + parentResult.computeStatus(); + response = handleException(parentResult, ex); + } + + finishRequest(task); + return response; + } + + @PostMapping("/rpc/generate") + public ResponseEntity generateValueRpc( + @RequestBody PolicyItemsDefinitionType policyItemsDefinition) { + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("generateValueRpc"); + + ResponseEntity response = generateValue(null, policyItemsDefinition, task, parentResult); + finishRequest(task); + + return response; + } + + private ResponseEntity generateValue( + PrismObject object, PolicyItemsDefinitionType policyItemsDefinition, + Task task, OperationResult parentResult) { + + ResponseEntity response; + if (policyItemsDefinition == null) { + response = createBadPolicyItemsDefinitionResponse("Policy items definition must not be null", parentResult); + } else { + try { + modelInteraction.generateValue(object, policyItemsDefinition, task, parentResult); + parentResult.computeStatusIfUnknown(); + if (parentResult.isSuccess()) { + response = createResponse(HttpStatus.OK, policyItemsDefinition, parentResult, true); + } else { + response = createResponse(HttpStatus.BAD_REQUEST, parentResult, parentResult); + } + + } catch (Exception ex) { + parentResult.recordFatalError("Failed to generate value, " + ex.getMessage(), ex); + response = handleException(parentResult, ex); + } + } + return response; + } + + @PostMapping("/{type}/{oid}/validate") + public ResponseEntity validateValue( + @PathVariable("type") String type, + @PathVariable("oid") String oid, + @RequestBody PolicyItemsDefinitionType policyItemsDefinition) { + + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("validateValue"); + + Class clazz = ObjectTypes.getClassFromRestType(type); + ResponseEntity response; + try { + PrismObject object = model.getObject(clazz, oid, null, task, parentResult); + response = validateValue(object, policyItemsDefinition, task, parentResult); + } catch (Exception ex) { + parentResult.computeStatus(); + response = handleException(parentResult, ex); + } + + finishRequest(task); + return response; + } + + @PostMapping("/rpc/validate") + public ResponseEntity validateValue( + @RequestBody PolicyItemsDefinitionType policyItemsDefinition) { + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("validateValue"); + + ResponseEntity response = validateValue(null, policyItemsDefinition, task, parentResult); + finishRequest(task); + return response; + } + + private ResponseEntity validateValue( + PrismObject object, PolicyItemsDefinitionType policyItemsDefinition, + Task task, OperationResult parentResult) { + ResponseEntity response; + if (policyItemsDefinition == null) { + response = createBadPolicyItemsDefinitionResponse("Policy items definition must not be null", parentResult); + finishRequest(task); + return response; + } + + if (CollectionUtils.isEmpty(policyItemsDefinition.getPolicyItemDefinition())) { + response = createBadPolicyItemsDefinitionResponse("No definitions for items", parentResult); + finishRequest(task); + return response; + } + + try { + modelInteraction.validateValue(object, policyItemsDefinition, task, parentResult); + + parentResult.computeStatusIfUnknown(); + if (parentResult.isAcceptable()) { + response = createResponse(HttpStatus.OK, policyItemsDefinition, parentResult, true); + } else { + response = ResponseEntity.status(HttpStatus.CONFLICT).body(parentResult); + } + + } catch (Exception ex) { + parentResult.computeStatus(); + response = handleException(parentResult, ex); + } + + return response; + } + + private ResponseEntity createBadPolicyItemsDefinitionResponse( + String message, OperationResult parentResult) { + logger.error(message); + parentResult.recordFatalError(message); + return status(HttpStatus.BAD_REQUEST).body(parentResult); + } + + @GetMapping("/users/{id}/policy") + public ResponseEntity getValuePolicyForUser( + @PathVariable("id") String oid) { + logger.debug("getValuePolicyForUser start"); + + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("getValuePolicyForUser"); + + ResponseEntity response; + try { + Collection> options = + SelectorOptions.createCollection(GetOperationOptions.createRaw()); + PrismObject user = model.getObject(UserType.class, oid, options, task, parentResult); + + CredentialsPolicyType policy = modelInteraction.getCredentialsPolicy(user, task, parentResult); + + response = createResponse(HttpStatus.OK, policy, parentResult); + } catch (Exception ex) { + response = handleException(parentResult, ex); + } + + parentResult.computeStatus(); + finishRequest(task); + + logger.debug("getValuePolicyForUser finish"); + return response; + } + + @GetMapping(GET_OBJECT_PATH) + public ResponseEntity getObject( + @PathVariable("type") String type, + @PathVariable("id") String id, + @RequestParam(value = "options", required = false) List options, + @RequestParam(value = "include", required = false) List include, + @RequestParam(value = "exclude", required = false) List exclude, + @RequestParam(value = "resolveNames", required = false) List resolveNames) { + logger.debug("model rest service for get operation start"); + + Task task = initRequest(); + OperationResult parentResult = createSubresult(task, "getObject"); + + Class clazz = ObjectTypes.getClassFromRestType(type); + Collection> getOptions = + GetOperationOptions.fromRestOptions(options, include, exclude, + resolveNames, DefinitionProcessingOption.ONLY_IF_EXISTS, prismContext); + + ResponseEntity response; + try { + PrismObject object; + if (NodeType.class.equals(clazz) && CURRENT.equals(id)) { + String nodeId = taskManager.getNodeId(); + ObjectQuery query = prismContext.queryFor(NodeType.class) + .item(NodeType.F_NODE_IDENTIFIER).eq(nodeId) + .build(); + List> objects = model.searchObjects(NodeType.class, query, getOptions, task, parentResult); + if (objects.isEmpty()) { + throw new ObjectNotFoundException("Current node (id " + nodeId + ") couldn't be found."); + } else if (objects.size() > 1) { + throw new IllegalStateException("More than one 'current' node (id " + nodeId + ") found."); + } else { + object = objects.get(0); + } + } else { + object = model.getObject(clazz, id, getOptions, task, parentResult); + } + removeExcludes(object, exclude); // temporary measure until fixed in repo + + response = createResponse(HttpStatus.OK, object, parentResult); + } catch (Exception ex) { + response = handleException(parentResult, ex); + } + + parentResult.computeStatus(); + finishRequest(task); + return response; + } + + @GetMapping("/self") + public ResponseEntity getSelf() { + logger.debug("model rest service for get operation start"); + Task task = initRequest(); + OperationResult parentResult = createSubresult(task, "self"); + ResponseEntity response; + + try { + FocusType loggedInUser = SecurityUtil.getPrincipal().getFocus(); + System.out.println("loggedInUser = " + loggedInUser); + PrismObject user = model.getObject(UserType.class, loggedInUser.getOid(), null, task, parentResult); + response = createResponse(HttpStatus.OK, user, parentResult, true); + parentResult.recordSuccessIfUnknown(); + } catch (SecurityViolationException | ObjectNotFoundException | SchemaException | + CommunicationException | ConfigurationException | ExpressionEvaluationException e) { + e.printStackTrace(); + response = status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage()); + } + + finishRequest(task); + return response; + } + + @PostMapping("/{type}") + public ResponseEntity addObject( + @PathVariable("type") String type, + @RequestParam(value = "options", required = false) List options, + @RequestBody PrismObject object) { + logger.debug("model rest service for add operation start"); + + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("addObject"); + + Class clazz = ObjectTypes.getClassFromRestType(type); + if (!object.getCompileTimeClass().equals(clazz)) { + finishRequest(task); + parentResult.recordFatalError("Request to add object of type " + + object.getCompileTimeClass().getSimpleName() + " to the collection of " + type); + return createErrorResponseBuilder(HttpStatus.BAD_REQUEST, parentResult); + } + + ModelExecuteOptions modelExecuteOptions = ModelExecuteOptions.fromRestOptions(options); + + String oid; + ResponseEntity response; + try { + oid = model.addObject(object, modelExecuteOptions, task, parentResult); + logger.debug("returned oid: {}", oid); + + if (oid != null) { + response = createResponseWithLocation( + clazz.isAssignableFrom(TaskType.class) ? HttpStatus.ACCEPTED : HttpStatus.CREATED, + uriGetObject(type, oid), + parentResult); + } else { + // OID might be null e.g. if the object creation is a subject of workflow approval + response = createResponse(HttpStatus.ACCEPTED, parentResult); + } + } catch (Exception ex) { + response = handleException(parentResult, ex); + } + + parentResult.computeStatus(); + finishRequest(task); + return response; + } + + @NotNull + public URI uriGetObject(@PathVariable("type") String type, String oid) { + return ServletUriComponentsBuilder.fromCurrentContextPath() + .path(BASE_PATH + GET_OBJECT_PATH) + .build(type, oid); + } + + @GetMapping("/{type}") + public ResponseEntity searchObjectsByType( + @PathVariable("type") String type, + @RequestParam(value = "options", required = false) List options, + @RequestParam(value = "include", required = false) List include, + @RequestParam(value = "exclude", required = false) List exclude, + @RequestParam(value = "resolveNames", required = false) List resolveNames) { + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("searchObjectsByType"); + + //noinspection unchecked + Class clazz = (Class) ObjectTypes.getClassFromRestType(type); + ResponseEntity response; + try { + + Collection> searchOptions = GetOperationOptions.fromRestOptions(options, include, + exclude, resolveNames, DefinitionProcessingOption.ONLY_IF_EXISTS, prismContext); + + List> objects = modelService.searchObjects(clazz, null, searchOptions, task, parentResult); + ObjectListType listType = new ObjectListType(); + for (PrismObject object : objects) { + listType.getObject().add(object.asObjectable()); + } + + response = createResponse(HttpStatus.OK, listType, parentResult, true); + } catch (Exception ex) { + response = handleException(parentResult, ex); + } + + parentResult.computeStatus(); + finishRequest(task); + return response; + } + + @PutMapping("/{type}/{id}") + public ResponseEntity addObject( + @PathVariable("type") String type, + @PathVariable("id") String id, // TODO is it OK that this is not used or at least asserted? + @RequestParam(value = "options", required = false) List options, + @RequestBody PrismObject object) { + logger.debug("model rest service for add operation start"); + + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("addObject"); + + Class clazz = ObjectTypes.getClassFromRestType(type); + if (!object.getCompileTimeClass().equals(clazz)) { + finishRequest(task); + parentResult.recordFatalError("Request to add object of type " + + object.getCompileTimeClass().getSimpleName() + + " to the collection of " + type); + return createErrorResponseBuilder(HttpStatus.BAD_REQUEST, parentResult); + } + + ModelExecuteOptions modelExecuteOptions = ModelExecuteOptions.fromRestOptions(options); + if (modelExecuteOptions == null) { + modelExecuteOptions = ModelExecuteOptions.createOverwrite(); + } else if (!ModelExecuteOptions.isOverwrite(modelExecuteOptions)) { + modelExecuteOptions.setOverwrite(Boolean.TRUE); + } + + String oid; + ResponseEntity response; + try { + oid = model.addObject(object, modelExecuteOptions, task, parentResult); + logger.debug("returned oid : {}", oid); + + response = createResponseWithLocation( + clazz.isAssignableFrom(TaskType.class) ? HttpStatus.ACCEPTED : HttpStatus.CREATED, + uriGetObject(type, oid), + parentResult); + } catch (Exception ex) { + response = handleException(parentResult, ex); + } + parentResult.computeStatus(); + + finishRequest(task); + return response; + } + + @DeleteMapping("/{type}/{id}") + public ResponseEntity deleteObject( + @PathVariable("type") String type, + @PathVariable("id") String id, + @RequestParam(value = "options", required = false) List options) { + + logger.debug("model rest service for delete operation start"); + + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("deleteObject"); + + Class clazz = ObjectTypes.getClassFromRestType(type); + ResponseEntity response; + try { + if (clazz.isAssignableFrom(TaskType.class)) { + taskService.suspendAndDeleteTask(id, WAIT_FOR_TASK_STOP, true, task, parentResult); + parentResult.computeStatus(); + finishRequest(task); + if (parentResult.isSuccess()) { + return ResponseEntity.noContent().build(); + } + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(parentResult.getMessage()); + } + + ModelExecuteOptions modelExecuteOptions = ModelExecuteOptions.fromRestOptions(options); + + model.deleteObject(clazz, id, modelExecuteOptions, task, parentResult); + response = createResponse(HttpStatus.NO_CONTENT, parentResult); + } catch (Exception ex) { + response = handleException(parentResult, ex); + } + + parentResult.computeStatus(); + finishRequest(task); + return response; + } + + @PostMapping("/{type}/{oid}") + public ResponseEntity modifyObjectPost( + @PathVariable("type") String type, + @PathVariable("oid") String oid, + @RequestParam(value = "options", required = false) List options, + @RequestBody ObjectModificationType modificationType) { + return modifyObjectPatch(type, oid, options, modificationType); + } + + @PatchMapping("/{type}/{oid}") + public ResponseEntity modifyObjectPatch( + @PathVariable("type") String type, + @PathVariable("oid") String oid, + @RequestParam(value = "options", required = false) List options, + @RequestBody ObjectModificationType modificationType) { + + logger.debug("model rest service for modify operation start"); + + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("modifyObjectPatch"); + + Class clazz = ObjectTypes.getClassFromRestType(type); + ResponseEntity response; + try { + ModelExecuteOptions modelExecuteOptions = ModelExecuteOptions.fromRestOptions(options); + Collection modifications = DeltaConvertor.toModifications(modificationType, clazz, prismContext); + model.modifyObject(clazz, oid, modifications, modelExecuteOptions, task, parentResult); + response = createResponse(HttpStatus.NO_CONTENT, parentResult); + } catch (Exception ex) { + parentResult.recordFatalError("Could not modify object. " + ex.getMessage(), ex); + response = handleException(parentResult, ex); + } + + parentResult.computeStatus(); + finishRequest(task); + return response; + } + + @PostMapping("/notifyChange") + public ResponseEntity notifyChange( + @RequestBody ResourceObjectShadowChangeDescriptionType changeDescription) { + logger.debug("model rest service for notify change operation start"); + Validate.notNull(changeDescription, "Chnage description must not be null"); + + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("notifyChange"); + + ResponseEntity response; + try { + modelService.notifyChange(changeDescription, task, parentResult); + response = createResponse(HttpStatus.OK, parentResult); + } catch (Exception ex) { + response = handleException(parentResult, ex); + } + + parentResult.computeStatus(); + finishRequest(task); + return response; + } + + @GetMapping("/shadows/{oid}/owner") + public ResponseEntity findShadowOwner( + @PathVariable("oid") String shadowOid) { + + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("findShadowOwner"); + + ResponseEntity response; + try { + PrismObject focus = modelService.searchShadowOwner(shadowOid, null, task, parentResult); + response = createResponse(HttpStatus.OK, focus, parentResult); + } catch (Exception ex) { + response = handleException(parentResult, ex); + } + + parentResult.computeStatus(); + finishRequest(task); + return response; + } + + @PostMapping("/shadows/{oid}/import") + public ResponseEntity importShadow( + @PathVariable("oid") String shadowOid) { + logger.debug("model rest service for import shadow from resource operation start"); + + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("importShadow"); + + ResponseEntity response; + try { + modelService.importFromResource(shadowOid, task, parentResult); + + response = createResponse(HttpStatus.OK, parentResult, parentResult); + } catch (Exception ex) { + response = handleException(parentResult, ex); + } + + parentResult.computeStatus(); + finishRequest(task); + return response; + } + + @PostMapping("/{type}/search") + public ResponseEntity searchObjects( + @PathVariable("type") String type, + @RequestParam(value = "options", required = false) List options, + @RequestParam(value = "include", required = false) List include, + @RequestParam(value = "exclude", required = false) List exclude, + @RequestParam(value = "resolveNames", required = false) List resolveNames, + @RequestBody QueryType queryType) { + + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("searchObjects"); + + Class clazz = ObjectTypes.getClassFromRestType(type); + ResponseEntity response; + try { + ObjectQuery query = prismContext.getQueryConverter().createObjectQuery(clazz, queryType); + Collection> searchOptions = GetOperationOptions.fromRestOptions(options, include, + exclude, resolveNames, DefinitionProcessingOption.ONLY_IF_EXISTS, prismContext); + List> objects = + model.searchObjects(clazz, query, searchOptions, task, parentResult); + + ObjectListType listType = new ObjectListType(); + for (PrismObject o : objects) { + removeExcludes(o, exclude); // temporary measure until fixed in repo + listType.getObject().add(o.asObjectable()); + } + + response = createResponse(HttpStatus.OK, listType, parentResult, true); + } catch (Exception ex) { + response = handleException(parentResult, ex); + } + + parentResult.computeStatus(); + finishRequest(task); + return response; + } + + private void removeExcludes(PrismObject object, List exclude) + throws SchemaException { + object.getValue().removePaths( + ItemPathCollectionsUtil.pathListFromStrings(exclude, prismContext)); + } + + @PostMapping("/resources/{resourceOid}/import/{objectClass}") + public ResponseEntity importFromResource( + @PathVariable("resourceOid") String resourceOid, + @PathVariable("objectClass") String objectClass) { + logger.debug("model rest service for import from resource operation start"); + + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("importFromResource"); + + QName objClass = new QName(MidPointConstants.NS_RI, objectClass); + ResponseEntity response; + try { + modelService.importFromResource(resourceOid, objClass, task, parentResult); + response = createResponseWithLocation( + HttpStatus.SEE_OTHER, + uriGetObject(ObjectTypes.TASK.getRestType(), task.getOid()), + parentResult); + } catch (Exception ex) { + response = handleException(parentResult, ex); + } + + parentResult.computeStatus(); + finishRequest(task); + return response; + } + + @PostMapping("/resources/{resourceOid}/test") + public ResponseEntity testResource( + @PathVariable("resourceOid") String resourceOid) { + logger.debug("model rest service for test resource operation start"); + + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("testResource"); + + ResponseEntity response; + OperationResult testResult = null; + try { + testResult = modelService.testResource(resourceOid, task); + response = createResponse(HttpStatus.OK, testResult, parentResult); + } catch (Exception ex) { + response = handleException(parentResult, ex); + } + + if (testResult != null) { + parentResult.getSubresults().add(testResult); + } + + finishRequest(task); + return response; + } + + @PostMapping("/tasks/{oid}/suspend") + public ResponseEntity suspendTask( + @PathVariable("oid") String taskOid) { + + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("suspendTask"); + + ResponseEntity response; + try { + taskService.suspendTask(taskOid, WAIT_FOR_TASK_STOP, task, parentResult); + parentResult.computeStatus(); + response = createResponse(HttpStatus.NO_CONTENT, task, parentResult); + } catch (Exception ex) { + response = handleException(parentResult, ex); + } + + finishRequest(task); + return response; + } + + @PostMapping("/tasks/{oid}/resume") + public ResponseEntity resumeTask( + @PathVariable("oid") String taskOid) { + + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("resumeTask"); + + ResponseEntity response; + try { + taskService.resumeTask(taskOid, task, parentResult); + parentResult.computeStatus(); + response = createResponse(HttpStatus.ACCEPTED, parentResult); + } catch (Exception ex) { + response = handleException(parentResult, ex); + } + + finishRequest(task); + return response; + } + + @PostMapping("tasks/{oid}/run") + public ResponseEntity scheduleTaskNow( + @PathVariable("oid") String taskOid) { + Task task = initRequest(); + OperationResult parentResult = task.getResult().createSubresult("scheduleTaskNow"); + + ResponseEntity response; + try { + taskService.scheduleTaskNow(taskOid, task, parentResult); + parentResult.computeStatus(); + response = createResponse(HttpStatus.NO_CONTENT, parentResult); + } catch (Exception ex) { + response = handleException(parentResult, ex); + } + + finishRequest(task); + return response; + } + + @PostMapping("/rpc/executeScript") + public ResponseEntity executeScript( + @RequestParam(value = "asynchronous", required = false) Boolean asynchronous, + @RequestBody ExecuteScriptType command) { + Task task = initRequest(); + OperationResult result = task.getResult().createSubresult("executeScript"); + + ResponseEntity response; + try { + if (Boolean.TRUE.equals(asynchronous)) { + scriptingService.evaluateExpressionInBackground(command, task, result); + response = createResponseWithLocation( + HttpStatus.CREATED, + uriGetObject(ObjectTypes.TASK.getRestType(), task.getOid()), + result); + } else { + ScriptExecutionResult executionResult = scriptingService.evaluateExpression( + command, VariablesMap.emptyMap(), false, task, result); + ExecuteScriptResponseType responseData = new ExecuteScriptResponseType() + .result(result.createOperationResultType()) + .output(new ExecuteScriptOutputType() + .consoleOutput(executionResult.getConsoleOutput()) + .dataOutput(PipelineData.prepareXmlData(executionResult.getDataOutput(), command.getOptions()))); + response = createResponse(HttpStatus.OK, responseData, result); + } + } catch (Exception ex) { + LoggingUtils.logUnexpectedException(logger, "Couldn't execute script.", ex); + response = handleExceptionNoLog(result, ex); + } + result.computeStatus(); + finishRequest(task); + return response; + } + + @PostMapping("/rpc/compare") +// @Consumes({ "application/xml" }) TODO do we need to limit it to XML? + public ResponseEntity compare( + @RequestParam(value = "readOptions", required = false) List restReadOptions, + @RequestParam(value = "compareOptions", required = false) List restCompareOptions, + @RequestParam(value = "ignoreItems", required = false) List restIgnoreItems, + @RequestBody PrismObject clientObject) { + + Task task = initRequest(); + OperationResult result = task.getResult().createSubresult("compare"); + + ResponseEntity response; + try { + List ignoreItemPaths = ItemPathCollectionsUtil.pathListFromStrings(restIgnoreItems, prismContext); + final GetOperationOptions getOpOptions = GetOperationOptions.fromRestOptions(restReadOptions, DefinitionProcessingOption.ONLY_IF_EXISTS); + Collection> readOptions = + getOpOptions != null ? SelectorOptions.createCollection(getOpOptions) : null; + ModelCompareOptions compareOptions = ModelCompareOptions.fromRestOptions(restCompareOptions); + CompareResultType compareResult = modelService.compareObject(clientObject, readOptions, compareOptions, ignoreItemPaths, task, result); + + response = createResponse(HttpStatus.OK, compareResult, result); + } catch (Exception ex) { + response = handleException(result, ex); + } + + result.computeStatus(); + finishRequest(task); + return response; + } + + @GetMapping(value = "/log/size", produces = MediaType.TEXT_PLAIN_VALUE) + public ResponseEntity getLogFileSize() { + + Task task = initRequest(); + OperationResult result = task.getResult().createSubresult("getLogFileSize"); + + ResponseEntity response; + try { + long size = modelDiagnosticService.getLogFileSize(task, result); + response = createResponse(HttpStatus.OK, String.valueOf(size), result); + } catch (Exception ex) { + response = handleException(result, ex); + } + + result.computeStatus(); + finishRequest(task); + return response; + } + + @GetMapping(value = "/log", produces = MediaType.TEXT_PLAIN_VALUE) + public ResponseEntity getLog( + @RequestParam(value = "fromPosition", required = false) Long fromPosition, + @RequestParam(value = "maxSize", required = false) Long maxSize) { + + Task task = initRequest(); + OperationResult result = task.getResult().createSubresult("getLog"); + + ResponseEntity response; + try { + LogFileContentType content = modelDiagnosticService.getLogFileContent(fromPosition, maxSize, task, result); + + ResponseEntity.BodyBuilder builder = ResponseEntity.ok(); + builder.header("ReturnedDataPosition", String.valueOf(content.getAt())); + builder.header("ReturnedDataComplete", String.valueOf(content.isComplete())); + builder.header("CurrentLogFileSize", String.valueOf(content.getLogFileSize())); + response = builder.body(content.getContent()); + } catch (Exception ex) { + LoggingUtils.logUnexpectedException(logger, "Cannot get log file content: fromPosition={}, maxSize={}", ex, fromPosition, maxSize); + response = handleExceptionNoLog(result, ex); + } + + result.computeStatus(); + finishRequest(task); + return response; + } + + @PostMapping("/users/{oid}/credential") + public ResponseEntity executeCredentialReset( + @PathVariable("oid") String oid, + @RequestBody ExecuteCredentialResetRequestType executeCredentialResetRequest) { + Task task = initRequest(); + OperationResult result = task.getResult().createSubresult("executeCredentialReset"); + + ResponseEntity response; + try { + PrismObject user = modelService.getObject(UserType.class, oid, null, task, result); + + ExecuteCredentialResetResponseType executeCredentialResetResponse = modelInteraction.executeCredentialsReset(user, executeCredentialResetRequest, task, result); + response = createResponse(HttpStatus.OK, executeCredentialResetResponse, result); + } catch (Exception ex) { + response = handleException(result, ex); + } + + result.computeStatus(); + finishRequest(task); + return response; + + } + + @GetMapping(value = "/threads", produces = MediaType.TEXT_PLAIN_VALUE) + public ResponseEntity getThreadsDump() { + Task task = initRequest(); + OperationResult result = task.getResult().createSubresult("getThreadsDump"); + + ResponseEntity response; + try { + String dump = taskService.getThreadsDump(task, result); + response = ResponseEntity.ok(dump); + } catch (Exception ex) { + LoggingUtils.logUnexpectedException(logger, "Cannot get threads dump", ex); + response = handleExceptionNoLog(result, ex); + } + result.computeStatus(); + finishRequest(task); + return response; + } + + @GetMapping(value = "/tasks/threads", produces = MediaType.TEXT_PLAIN_VALUE) + public ResponseEntity getRunningTasksThreadsDump() { + + Task task = initRequest(); + OperationResult result = task.getResult().createSubresult("getRunningTasksThreadsDump"); + + ResponseEntity response; + try { + String dump = taskService.getRunningTasksThreadsDump(task, result); + response = ResponseEntity.ok(dump); + } catch (Exception ex) { + LoggingUtils.logUnexpectedException(logger, "Cannot get running tasks threads dump", ex); + response = handleExceptionNoLog(result, ex); + } + result.computeStatus(); + finishRequest(task); + return response; + } + + @GetMapping(value = "/tasks/{oid}/threads", produces = MediaType.TEXT_PLAIN_VALUE) + public ResponseEntity getTaskThreadsDump( + @PathVariable("oid") String oid) { + Task task = initRequest(); + OperationResult result = task.getResult().createSubresult("getTaskThreadsDump"); + + ResponseEntity response; + try { + String dump = taskService.getTaskThreadsDump(oid, task, result); + response = ResponseEntity.ok(dump); + } catch (Exception ex) { + LoggingUtils.logUnexpectedException(logger, "Cannot get task threads dump for task " + oid, ex); + response = handleExceptionNoLog(result, ex); + } + result.computeStatus(); + finishRequest(task); + return response; + } +} diff --git a/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/RestApiIndex.java b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/RestApiIndex.java new file mode 100644 index 00000000000..edd3b2eab4e --- /dev/null +++ b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/RestApiIndex.java @@ -0,0 +1,143 @@ +package com.evolveum.midpoint.rest.impl; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.mvc.condition.MediaTypeExpression; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; +import org.springframework.web.util.UriComponentsBuilder; + +/** + * Support for simple index page with REST API endpoints (HTML and JSON). + */ +@RestController +@RequestMapping("/rest2") +public class RestApiIndex { + + private final List uiRestInfo; + + public RestApiIndex(RequestMappingHandlerMapping handlerMapping) { + uiRestInfo = operationInfoStream(handlerMapping) + .filter(info -> info.handler.getBeanType().getName() + .startsWith("com.evolveum.midpoint.rest.")) + .collect(Collectors.toList()); + } + + private Stream operationInfoStream(RequestMappingHandlerMapping handlerMapping) { + return handlerMapping.getHandlerMethods().entrySet().stream() + .map(entry -> new OperationInfo(entry.getKey(), entry.getValue())); + } + + @GetMapping() + public List index() { + return uiRestInfo.stream() + .flatMap(OperationInfo::operationJsonStream) + .sorted(Comparator.comparing(json -> json.urlPattern)) + .collect(Collectors.toList()); + } + + @GetMapping(produces = "text/html") + public String indexHtml() { + StringBuilder html = new StringBuilder("" + + "REST-ish API" + + "" + + "" + + "

REST operations

This is NOT Swagger! Click at your own risk!") + .toString(); + } + + private static class OperationInfo { + final RequestMappingInfo mappingInfo; + final HandlerMethod handler; + + OperationInfo(RequestMappingInfo mappingInfo, HandlerMethod handler) { + this.mappingInfo = mappingInfo; + this.handler = handler; + } + + Stream operationJsonStream() { + return mappingInfo.getPatternsCondition().getPatterns().stream() + .map(pattern -> new OperationJson(pattern, + mappingInfo.getMethodsCondition().getMethods(), + mappingInfo.getConsumesCondition().getConsumableMediaTypes(), + mappingInfo.getProducesCondition().getExpressions())); + } + } + + @SuppressWarnings("WeakerAccess") + public static class OperationJson { + public final String urlPattern; + public final String[] methods; + public final String[] accepts; + public final String[] produces; + + public OperationJson(String urlPattern, + Set methods, + Set accepts, + Set produces) { + this.urlPattern = urlPattern; + this.methods = toStringArray(methods); + this.accepts = toStringArray(accepts); + this.produces = toStringArray(produces); + } + + private String[] toStringArray(Collection collection) { + return collection.isEmpty() + ? null + : collection.stream() + .map(Object::toString) + .toArray(String[]::new); + } + } + + // DEBUG area + @Autowired(required = false) + private List configurers; + + @Autowired + private List> converters; + + @Autowired + private RequestMappingHandlerAdapter requestMappingHandlerAdapter; + + @GetMapping("/config") + public Map config( + UriComponentsBuilder uriComponentsBuilder) { + Map result = new LinkedHashMap<>(); + result.put("configurers", toStrings(configurers)); + result.put("converters", toStrings(converters)); + result.put("requestMappingHandlerAdapter-converters", + toStrings(requestMappingHandlerAdapter.getMessageConverters())); + return result; + } + + private Object toStrings(Collection collection) { + return collection != null + ? collection.stream().map(Object::toString).collect(Collectors.toList()) + : "N/A"; + } +} diff --git a/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/RestConfig.java b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/RestConfig.java new file mode 100644 index 00000000000..9d3a537013f --- /dev/null +++ b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/RestConfig.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010-2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.rest.impl; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.MediaType; +import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import com.evolveum.midpoint.common.LocalizationService; +import com.evolveum.midpoint.prism.PrismContext; + +/** + * Spring configuration for MVC-based REST service. TODO: experimental as of early 2020 + * This prepares needed XML/JSON/YAML message converters. + * It also drives the package scan for REST controllers under this package. + */ +@Configuration +@ComponentScan +public class RestConfig + implements WebMvcConfigurer { + + // TODO probably @Override addArgumentResolvers for @Converter processing? + + @Override + public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { + for (MediaType mediaType : MidpointYamlHttpMessageConverter.MEDIA_TYPES) { + configurer.mediaType(mediaType.getSubtype(), mediaType); + } + configurer.defaultContentType(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML); + } + + @Bean + public MidpointYamlHttpMessageConverter yamlConverter( + PrismContext prismContext, LocalizationService localizationService) { + return new MidpointYamlHttpMessageConverter(prismContext, localizationService); + } + + @Bean + public MidpointXmlHttpMessageConverter xmlConverter( + PrismContext prismContext, LocalizationService localizationService) { + return new MidpointXmlHttpMessageConverter(prismContext, localizationService); + } + + @Bean + public MidpointJsonHttpMessageConverter jsonConverter( + PrismContext prismContext, LocalizationService localizationService) { + return new MidpointJsonHttpMessageConverter(prismContext, localizationService); + } +} diff --git a/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/RestExceptionHandler.java b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/RestExceptionHandler.java new file mode 100644 index 00000000000..bedf428d53f --- /dev/null +++ b/model/rest-impl/src/main/java/com/evolveum/midpoint/rest/impl/RestExceptionHandler.java @@ -0,0 +1,55 @@ +package com.evolveum.midpoint.rest.impl; + +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; + +import java.util.LinkedHashMap; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; + +@ControllerAdvice +public class RestExceptionHandler { + + private static final Trace LOGGER = TraceManager.getTrace(RestExceptionHandler.class); + + /* + * TODO only catch all at the moment, later I'l diversify it to various + * Seems to be working for exceptions, but not for 404. + * 404 worked with: + * spring.mvc.throw-exception-if-no-handler-found=true + * spring.resources.add-mappings=false + * But this broke images (and perhaps other static content) serving for Wicket app. + */ + + @ExceptionHandler(Exception.class) + public ResponseEntity defaultHandler( + Exception ex, HttpServletRequest request, HttpServletResponse response) { + LOGGER.warn("Unexpected exception causing HTTP 500", ex); + return errorResponse(INTERNAL_SERVER_ERROR, request, ex.getMessage()); + } + + private ResponseEntity errorResponse( + HttpStatus status, HttpServletRequest request, String message) { + LOGGER.debug("HTTP error status {} with message: {}", status.value(), message); + return ResponseEntity.status(status) + .body(createErrorDto(request, status, message)); + } + + public static Map createErrorDto( + HttpServletRequest request, HttpStatus status, String message) { + Map errorDto = new LinkedHashMap<>(); + errorDto.put("error", status.getReasonPhrase()); + errorDto.put("message", message); + errorDto.put("status", status.value()); + errorDto.put("path", request.getRequestURI()); + return errorDto; + } +} diff --git a/pom.xml b/pom.xml index 8e0d0376d8b..15b61d199ee 100644 --- a/pom.xml +++ b/pom.xml @@ -165,9 +165,6 @@ 3.141.59 1.7.25 1.2.3 - - 5.1.9.RELEASE - 5.1.6.RELEASE 2.0.0.M30 1.2.1.Final 3.5.0 @@ -201,7 +198,6 @@ 1.4.0 7.1.1 7.0 - 2.3.1 1.1.3 9.4.20.v20190813 3.6.2 @@ -219,11 +215,6 @@ javax.xml.soap-api ${javax.xml.soap.version} - - javax.xml.ws - jaxws-api - ${jaxws-api.version} - org.apache.geronimo.specs geronimo-ws-metadata_2.0_spec @@ -959,7 +950,7 @@ org.springframework spring-core - ${spring.version} + ${spring-framework.version} @@ -1764,6 +1755,7 @@ org.slf4j:jcl-over-slf4j org.slf4j:slf4j-api org.danekja:jdk-serializable-functional + org.apache.tomcat.embed:tomcat-embed-core @@ -1778,7 +1770,9 @@ maven-checkstyle-plugin ${checkstyle.version} + ${maven.multiModuleProjectDirectory}/config/checkstyle/checkstyle.xml + ${maven.multiModuleProjectDirectory}/config/checkstyle/checkstyle-suppressions.xml UTF-8 true @@ -2029,6 +2023,7 @@ ${checkstyle.version} + ${maven.multiModuleProjectDirectory}/build-system/checkstyle-configs/checkstyle.xml UTF-8 diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceCache.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceCache.java index f8fb87a2b14..01a01db660c 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceCache.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceCache.java @@ -111,20 +111,20 @@ synchronized PrismObject get(@NotNull String oid, String requested PrismObject resourceToReturn; PrismObject cachedResource = cache.get(oid); if (cachedResource == null) { - LOGGER.debug("MISS(not cached) for {}", oid); + LOGGER.debug("MISS(not cached) for {} (get)", oid); resourceToReturn = null; } else if (!compareVersion(requestedVersion, cachedResource.getVersion())) { - LOGGER.debug("MISS(wrong version) for {}", oid); + LOGGER.debug("MISS(wrong version) for {} (req={}, actual={})", oid, requestedVersion, cachedResource.getVersion()); LOGGER.trace("Cached resource version {} does not match requested resource version {}, purging from cache", cachedResource.getVersion(), requestedVersion); cache.remove(oid); resourceToReturn = null; } else if (readOnly) { cachedResource.checkImmutable(); - LOGGER.trace("HIT(read only) for {}", cachedResource); + LOGGER.trace("HIT(read only) for {} (v{})", cachedResource, cachedResource.getVersion()); resourceToReturn = cachedResource; } else { - LOGGER.debug("HIT(returning clone) for {}", cachedResource); + LOGGER.debug("HIT(returning clone) for {} (v{})", cachedResource, cachedResource.getVersion()); resourceToReturn = cachedResource.clone(); } @@ -151,7 +151,7 @@ PrismObject getIfLatest(@NotNull String oid, boolean readonly, Ope String version = repositoryService.getVersion(ResourceType.class, oid, parentResult); return get(oid, version, readonly); } else { - LOGGER.debug("MISS(not cached) for {}", oid); + LOGGER.debug("MISS(not cached) for {} (getIfLatest)", oid); CachePerformanceCollector.INSTANCE.registerMiss(ResourceCache.class, ResourceType.class, PER_CACHE); InternalMonitor.getResourceCacheStats().recordMiss(); return null; diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceManager.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceManager.java index 93525a7b1e1..d78a8110ef7 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceManager.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceManager.java @@ -1,1481 +1,1454 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.provisioning.impl; - -import java.util.*; - -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; -import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl; -import com.evolveum.midpoint.prism.*; -import com.evolveum.midpoint.prism.delta.*; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.schema.MutablePrismSchema; -import com.evolveum.midpoint.schema.processor.*; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import com.evolveum.prism.xml.ns._public.types_3.SchemaDefinitionType; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.Validate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Component; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.prism.schema.PrismSchema; -import com.evolveum.midpoint.provisioning.api.GenericConnectorException; -import com.evolveum.midpoint.provisioning.ucf.api.ConnectorInstance; -import com.evolveum.midpoint.provisioning.ucf.api.ExecuteProvisioningScriptOperation; -import com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException; -import com.evolveum.midpoint.provisioning.util.ProvisioningUtil; -import com.evolveum.midpoint.repo.api.RepositoryService; -import com.evolveum.midpoint.repo.common.expression.Expression; -import com.evolveum.midpoint.repo.common.expression.ExpressionEvaluationContext; -import com.evolveum.midpoint.repo.common.expression.ExpressionFactory; -import com.evolveum.midpoint.repo.common.expression.ExpressionVariables; -import com.evolveum.midpoint.schema.CapabilityUtil; -import com.evolveum.midpoint.schema.GetOperationOptions; -import com.evolveum.midpoint.schema.constants.ConnectorTestOperation; -import com.evolveum.midpoint.schema.internals.InternalCounters; -import com.evolveum.midpoint.schema.internals.InternalMonitor; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.statistics.ConnectorOperationalStatus; -import com.evolveum.midpoint.schema.util.ConnectorTypeUtil; -import com.evolveum.midpoint.schema.util.MiscSchemaUtil; -import com.evolveum.midpoint.schema.util.ObjectTypeUtil; -import com.evolveum.midpoint.schema.util.ResourceTypeUtil; -import com.evolveum.midpoint.task.api.StateReporter; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.DOMUtil; -import com.evolveum.midpoint.util.DebugUtil; -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.util.exception.SystemException; -import com.evolveum.midpoint.util.exception.TunnelException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationCapabilityType; -import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.CapabilityType; -import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.SchemaCapabilityType; -import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ScriptCapabilityType; - -@Component -public class ResourceManager { - - @Autowired @Qualifier("cacheRepositoryService") - private RepositoryService repositoryService; - - @Autowired private ResourceCache resourceCache; - @Autowired private ConnectorManager connectorManager; - @Autowired private PrismContext prismContext; - @Autowired private ExpressionFactory expressionFactory; - @Autowired private ResourceOperationalStateManager operationalStateManager; - - private static final Trace LOGGER = TraceManager.getTrace(ResourceManager.class); - - private static final String OP_COMPLETE_RESOURCE = ResourceManager.class.getName() + ".completeResource"; - - /** - * Completes a resource that has been - we expect - just retrieved from the repository, usually by a search operation. - */ - PrismObject completeResource(PrismObject repositoryObject, GetOperationOptions options, Task task, - OperationResult parentResult) - throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException { - - String oid = repositoryObject.getOid(); - boolean readonly = GetOperationOptions.isReadOnly(options); - - PrismObject cachedResource = resourceCache.get(oid, repositoryObject.getVersion(), readonly); - if (cachedResource != null) { - return cachedResource; - } else { - LOGGER.debug("Storing fetched resource {}, version {} to cache (previously cached version {})", - oid, repositoryObject.getVersion(), resourceCache.getVersion(oid)); - PrismObject mutableRepositoryObject = repositoryObject.cloneIfImmutable(); - return completeAndCacheResource(mutableRepositoryObject, options, task, parentResult); - } - } - - /** - * Gets a resource. - */ - public PrismObject getResource(String oid, GetOperationOptions options, Task task, OperationResult parentResult) - throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException { - boolean readonly = GetOperationOptions.isReadOnly(options); - PrismObject cachedResource = resourceCache.getIfLatest(oid, readonly, parentResult); - if (cachedResource != null) { - LOGGER.trace("Returning resource from cache:\n{}", cachedResource.debugDumpLazily()); - return cachedResource; - } else { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Fetching resource {} and storing to cache (previously cached version {})", - oid, resourceCache.getVersion(oid)); - } - // We must obviously NOT fetch resource from repo as read-only. We are going to modify it. - PrismObject repositoryObject = readResourceFromRepository(oid, parentResult); - return completeAndCacheResource(repositoryObject, options, task, parentResult); - } - } - - private PrismObject readResourceFromRepository(String oid, OperationResult parentResult) - throws ObjectNotFoundException, SchemaException { - InternalMonitor.recordCount(InternalCounters.RESOURCE_REPOSITORY_READ_COUNT); - return repositoryService.getObject(ResourceType.class, oid, null, parentResult); - } - - /** - * Here we complete the resource and cache it. - * - * @param repositoryObject Up-to-date repository object. Must be mutable. - */ - private PrismObject completeAndCacheResource(PrismObject repositoryObject, - GetOperationOptions options, Task task, OperationResult parentResult) - throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException { - - checkMutable(repositoryObject); - - PrismObject completedResource = completeResourceInternal(repositoryObject, null, - false, null, options, task, parentResult); - - logResourceAfterCompletion(completedResource); - if (!isComplete(completedResource)) { - // No not cache non-complete resources (e.g. those retrieved with noFetch) - LOGGER.trace("Not putting {} into cache because it's not complete", repositoryObject); - } else { - OperationResult completeResourceResult = parentResult.findSubresult(OP_COMPLETE_RESOURCE); - if (!completeResourceResult.isSuccess()) { - LOGGER.trace("Not putting {} into cache because the completeResource operation status is {}", - ObjectTypeUtil.toShortString(repositoryObject), completeResourceResult.getStatus()); - } else { - // Cache only resources that are completely OK - resourceCache.put(completedResource); - } - } - return completedResource; - } - - private void logResourceAfterCompletion(PrismObject completedResource) { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Resource after completion, before putting into cache:\n{}", completedResource.debugDump()); - Element xsdSchemaElement = ResourceTypeUtil.getResourceXsdSchema(completedResource); - if (xsdSchemaElement == null) { - LOGGER.trace("Schema: null"); - } else { - LOGGER.trace("Schema:\n{}", - DOMUtil.serializeDOMToString(ResourceTypeUtil.getResourceXsdSchema(completedResource))); - } - } - } - - void deleteResource(String oid, OperationResult parentResult) throws ObjectNotFoundException { - resourceCache.remove(oid); - repositoryService.deleteObject(ResourceType.class, oid, parentResult); - } - - /** - * Make sure that the resource is complete. - * - * It will check if the resource has a sufficiently fresh schema, etc. - * - * Returned resource may be the same or may be a different instance, but it - * is guaranteed that it will be "fresher" and will correspond to the - * repository state (assuming that the provided resource also corresponded - * to the repository state). - * - * The connector schema that was fetched before can be supplied to this - * method. This is just an optimization. It comes handy e.g. in test - * connection case. - * - * Note: This is not really the best place for this method. Need to figure - * out correct place later. - * - * @param repoResource - * Resource to check - * @param resourceSchema - * schema that was freshly pre-fetched (or null) - * - * @return completed resource - */ - private PrismObject completeResourceInternal(PrismObject repoResource, ResourceSchema resourceSchema, - boolean fetchedSchema, Map> capabilityMap, GetOperationOptions options, Task task, OperationResult parentResult) - throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException { - - checkMutable(repoResource); - - OperationResult result = parentResult.createMinorSubresult(OP_COMPLETE_RESOURCE); - try { - try { - applyConnectorSchemasToResource(repoResource, task, result); - } catch (Throwable t) { - String message = - "An error occurred while applying connector schema to connector configuration of " + repoResource + ": " - + t.getMessage(); - result.recordPartialError(message, t); - LOGGER.warn(message, t); - return repoResource; - } - - PrismObject newResource; - - if (isComplete(repoResource)) { - // The resource is complete. - newResource = repoResource; - - } else { - // The resource is NOT complete. Try to fetch schema and capabilities - - if (GetOperationOptions.isNoFetch(options)) { - // We need to fetch schema, but the noFetch option is specified. Therefore return whatever we have. - result.recordSuccessIfUnknown(); - return repoResource; - } - - try { - - completeSchemaAndCapabilities(repoResource, resourceSchema, fetchedSchema, capabilityMap, result); - - } catch (Exception ex) { - // Catch the exceptions. There are not critical. We need to catch them all because the connector may - // throw even undocumented runtime exceptions. - // Even non-complete resource may still be usable. The fetchResult indicates that there was an error - result.recordPartialError("Cannot complete resource schema and capabilities: " + ex.getMessage(), ex); - return repoResource; - } - - try { - // Now we need to re-read the resource from the repository and re-apply the schemas. This ensures that we will - // cache the correct version and that we avoid race conditions, etc. - - newResource = readResourceFromRepository(repoResource.getOid(), result); - applyConnectorSchemasToResource(newResource, task, result); - - } catch (SchemaException | ObjectNotFoundException | RuntimeException e) { - result.recordFatalError(e); - throw e; - } - } - - try { - // make sure it has parsed resource and refined schema. We are going to cache - // it, so we want to cache it with the parsed schemas - RefinedResourceSchemaImpl.getResourceSchema(newResource, prismContext); - RefinedResourceSchemaImpl.getRefinedSchema(newResource); - - } catch (SchemaException e) { - String message = "Schema error while processing schemaHandling section of " + newResource + ": " + e.getMessage(); - result.recordPartialError(message, e); - LOGGER.warn(message, e); - return newResource; - } catch (RuntimeException e) { - String message = - "Unexpected error while processing schemaHandling section of " + newResource + ": " + e.getMessage(); - result.recordPartialError(message, e); - LOGGER.warn(message, e); - return newResource; - } - - result.recordSuccessIfUnknown(); - - return newResource; - } catch (Throwable t) { - result.recordFatalError(t); - throw t; - } finally { - result.computeStatusIfUnknown(); - } - } - - private boolean isComplete(PrismObject resource) { - ResourceType resourceType = resource.asObjectable(); - if (ResourceTypeUtil.getResourceXsdSchema(resource) == null) { - return false; - } - CapabilitiesType capabilitiesType = resourceType.getCapabilities(); - return capabilitiesType != null && capabilitiesType.getCachingMetadata() != null; - } - - - private void completeSchemaAndCapabilities(PrismObject resource, ResourceSchema resourceSchema, boolean fetchedSchema, - Map> capabilityMap, OperationResult result) - throws SchemaException, CommunicationException, ObjectNotFoundException, GenericFrameworkException, ConfigurationException { - - Collection> modifications = new ArrayList<>(); - - // Capabilities - // we need to process capabilities first. Schema is one of the connector capabilities. - // We need to determine this capability to select the right connector for schema retrieval. - completeCapabilities(resource, capabilityMap != null, capabilityMap, modifications, result); - - if (resourceSchema == null) { - // Try to get existing schema from resource. We do not want to override this if it exists - // (but we still want to refresh the capabilities, that happens below) - resourceSchema = RefinedResourceSchemaImpl.getResourceSchema(resource, prismContext); - } - - if (resourceSchema == null || resourceSchema.isEmpty()) { - - LOGGER.trace("Fetching resource schema for {}", resource); - - resourceSchema = fetchResourceSchema(resource, capabilityMap, result); - - if (resourceSchema == null) { - LOGGER.warn("No resource schema fetched from {}", resource); - } else if (resourceSchema.isEmpty()) { - LOGGER.warn("Empty resource schema fetched from {}", resource); - } else { - LOGGER.debug("Fetched resource schema for {}: {} definitions", resource, resourceSchema.getDefinitions().size()); - fetchedSchema = true; - } - } - - if (resourceSchema != null) { - if (fetchedSchema) { - adjustSchemaForSimulatedCapabilities(resource, resourceSchema); - modifications.add(createSchemaUpdateDelta(resource, resourceSchema)); - AvailabilityStatusType previousStatus = ResourceTypeUtil.getLastAvailabilityStatus(resource.asObjectable()); - if (previousStatus != AvailabilityStatusType.UP) { - modifications.addAll(operationalStateManager.createAndLogOperationalStateDeltas(previousStatus, - AvailabilityStatusType.UP, resource.toString(), - "resource schema was successfully fetched", resource)); - } else { - // just for sure (if the status changed in the meanwhile) - modifications.add(operationalStateManager.createAvailabilityStatusDelta(AvailabilityStatusType.UP)); - } - } else { - CachingMetadataType schemaCachingMetadata = resource.asObjectable().getSchema().getCachingMetadata(); - if (schemaCachingMetadata == null) { - schemaCachingMetadata = MiscSchemaUtil.generateCachingMetadata(); - modifications.add( - prismContext.deltaFactory().property().createModificationReplaceProperty( - ItemPath.create(ResourceType.F_SCHEMA, CapabilitiesType.F_CACHING_METADATA), - resource.getDefinition(), - schemaCachingMetadata) - ); - } - } - } - - if (!modifications.isEmpty()) { - try { - LOGGER.trace("Completing {}:\n{}", resource, DebugUtil.debugDumpLazily(modifications, 1)); - repositoryService.modifyObject(ResourceType.class, resource.getOid(), modifications, result); - InternalMonitor.recordCount(InternalCounters.RESOURCE_REPOSITORY_MODIFY_COUNT); - } catch (ObjectAlreadyExistsException ex) { - // This should not happen - throw new SystemException(ex); - } - } - } - - private void completeCapabilities(PrismObject resource, boolean forceRefresh, Map> capabilityMap, Collection> modifications, - OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException { - ResourceType resourceType = resource.asObjectable(); - ConnectorSpec defaultConnectorSpec = getDefaultConnectorSpec(resource); - CapabilitiesType resourceCapType = resourceType.getCapabilities(); - if (resourceCapType == null) { - resourceCapType = new CapabilitiesType(); - resourceType.setCapabilities(resourceCapType); - } - completeConnectorCapabilities(defaultConnectorSpec, resourceCapType, ResourceType.F_CAPABILITIES, forceRefresh, - capabilityMap==null?null:capabilityMap.get(null), - modifications, result); - - for (ConnectorInstanceSpecificationType additionalConnectorType: resource.asObjectable().getAdditionalConnector()) { - ConnectorSpec connectorSpec = getConnectorSpec(resource, additionalConnectorType); - CapabilitiesType connectorCapType = additionalConnectorType.getCapabilities(); - if (connectorCapType == null) { - connectorCapType = new CapabilitiesType(); - additionalConnectorType.setCapabilities(connectorCapType); - } - ItemPath itemPath = additionalConnectorType.asPrismContainerValue().getPath().append(ConnectorInstanceSpecificationType.F_CAPABILITIES); - completeConnectorCapabilities(connectorSpec, connectorCapType, itemPath, forceRefresh, - capabilityMap==null?null:capabilityMap.get(additionalConnectorType.getName()), - modifications, result); - } - } - - private void completeConnectorCapabilities(ConnectorSpec connectorSpec, CapabilitiesType capType, ItemPath itemPath, boolean forceRefresh, - Collection retrievedCapabilities, Collection> modifications, OperationResult result) - throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { - - if (capType.getNative() != null && !capType.getNative().getAny().isEmpty()) { - if (!forceRefresh) { - CachingMetadataType cachingMetadata = capType.getCachingMetadata(); - if (cachingMetadata == null) { - cachingMetadata = MiscSchemaUtil.generateCachingMetadata(); - modifications.add( - prismContext.deltaFactory().property().createModificationReplaceProperty( - ItemPath.create(ResourceType.F_CAPABILITIES, CapabilitiesType.F_CACHING_METADATA), - connectorSpec.getResource().getDefinition(), - cachingMetadata) - ); - } - return; - } - } - - if (retrievedCapabilities == null) { - try { - - InternalMonitor.recordCount(InternalCounters.CONNECTOR_CAPABILITIES_FETCH_COUNT); - - ConnectorInstance connector = connectorManager.getConfiguredConnectorInstance(connectorSpec, false, result); - retrievedCapabilities = connector.fetchCapabilities(result); - - } catch (GenericFrameworkException e) { - throw new GenericConnectorException("Generic error in connector " + connectorSpec + ": " - + e.getMessage(), e); - } - } - - CapabilityCollectionType nativeCapType = new CapabilityCollectionType(); - capType.setNative(nativeCapType); - nativeCapType.getAny().addAll(retrievedCapabilities); - - CachingMetadataType cachingMetadata = MiscSchemaUtil.generateCachingMetadata(); - capType.setCachingMetadata(cachingMetadata); - - //noinspection unchecked - ObjectDelta capabilitiesReplaceDelta = prismContext.deltaFactory().object() - .createModificationReplaceContainer(ResourceType.class, connectorSpec.getResource().getOid(), - itemPath, capType.asPrismContainerValue().clone()); - - modifications.addAll(capabilitiesReplaceDelta.getModifications()); - } - - private ContainerDelta createSchemaUpdateDelta(PrismObject resource, ResourceSchema resourceSchema) throws SchemaException { - Document xsdDoc; - try { - xsdDoc = resourceSchema.serializeToXsd(); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Serialized XSD resource schema for {}:\n{}", resource, DOMUtil.serializeDOMToString(xsdDoc)); - } - } catch (SchemaException e) { - throw new SchemaException("Error processing resource schema for " + resource + ": " + e.getMessage(), e); - } - - Element xsdElement = DOMUtil.getFirstChildElement(xsdDoc); - if (xsdElement == null) { - throw new SchemaException("No schema was generated for " + resource); - } - CachingMetadataType cachingMetadata = MiscSchemaUtil.generateCachingMetadata(); - - ContainerDelta schemaContainerDelta = prismContext.deltaFactory().container().createDelta( - ResourceType.F_SCHEMA, ResourceType.class); - PrismContainerValue cval = prismContext.itemFactory().createContainerValue(); - schemaContainerDelta.setValueToReplace(cval); - PrismProperty cachingMetadataProperty = cval - .createProperty(XmlSchemaType.F_CACHING_METADATA); - cachingMetadataProperty.setRealValue(cachingMetadata); - List objectClasses = ResourceTypeUtil.getSchemaGenerationConstraints(resource); - if (objectClasses != null) { - PrismProperty generationConstraints = cval - .createProperty(XmlSchemaType.F_GENERATION_CONSTRAINTS); - SchemaGenerationConstraintsType constraints = new SchemaGenerationConstraintsType(); - constraints.getGenerateObjectClass().addAll(objectClasses); - generationConstraints.setRealValue(constraints); - } - PrismProperty definitionProperty = cval.createProperty(XmlSchemaType.F_DEFINITION); - ObjectTypeUtil.setXsdSchemaDefinition(definitionProperty, xsdElement); - - return schemaContainerDelta; - } - - /** - * Apply proper definition (connector schema) to the resource. - */ - private void applyConnectorSchemasToResource(PrismObject resource, Task task, OperationResult result) - throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException { - checkMutable(resource); - PrismObjectDefinition newResourceDefinition = resource.getDefinition().clone(); - for (ConnectorSpec connectorSpec : getAllConnectorSpecs(resource)) { - try { - applyConnectorSchemaToResource(connectorSpec, newResourceDefinition, resource, task, result); - } catch (CommunicationException | ConfigurationException | SecurityViolationException e) { - throw new IllegalStateException("Unexpected exception: " + e.getMessage(), e); // fixme temporary solution - } - } - resource.setDefinition(newResourceDefinition); - } - - /** - * Apply proper definition (connector schema) to the resource. - */ - private void applyConnectorSchemaToResource(ConnectorSpec connectorSpec, PrismObjectDefinition resourceDefinition, - PrismObject resource, Task task, OperationResult result) - throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException { - - ConnectorType connectorType = connectorManager.getConnector(connectorSpec, result); - PrismSchema connectorSchema = connectorManager.getAttachedConnectorSchema(connectorType); - PrismContainerDefinition configurationContainerDefinition = ConnectorTypeUtil - .findConfigurationContainerDefinition(connectorType, connectorSchema); - if (configurationContainerDefinition == null) { - throw new SchemaException("No configuration container definition in schema of " + connectorType); - } - - configurationContainerDefinition = configurationContainerDefinition.clone(); - PrismContainer configurationContainer = connectorSpec.getConnectorConfiguration(); - // We want element name, minOccurs/maxOccurs and similar definition to be taken from the original, not the schema - // the element is global in the connector schema. therefore it does not have correct maxOccurs - if (configurationContainer != null) { - configurationContainerDefinition.adoptElementDefinitionFrom(configurationContainer.getDefinition()); - configurationContainer.applyDefinition(configurationContainerDefinition, true); - - try { - //noinspection unchecked - configurationContainer.accept(visitable -> { - if ((visitable instanceof PrismProperty)) { - try { - evaluateExpression((PrismProperty)visitable, resource, task, result); - } catch (SchemaException | ObjectNotFoundException | ExpressionEvaluationException | CommunicationException | ConfigurationException | SecurityViolationException e) { - throw new TunnelException(e); - } - } - // TODO treat configuration items that are containers themselves - }); - } catch (TunnelException te) { - Throwable e = te.getCause(); - if (e instanceof SchemaException) { - throw (SchemaException)e; - } else if (e instanceof ObjectNotFoundException) { - throw (ObjectNotFoundException)e; - } else if (e instanceof ExpressionEvaluationException) { - throw (ExpressionEvaluationException)e; - } else if (e instanceof CommunicationException) { - throw (CommunicationException)e; - } else if (e instanceof ConfigurationException) { - throw (ConfigurationException)e; - } else if (e instanceof SecurityViolationException) { - throw (SecurityViolationException)e; - } else if (e instanceof RuntimeException) { - throw (RuntimeException)e; - } else if (e instanceof Error) { - throw (Error)e; - } else { - throw new SystemException(e); - } - } - - } else { - configurationContainerDefinition.adoptElementDefinitionFrom( - resourceDefinition.findContainerDefinition(ResourceType.F_CONNECTOR_CONFIGURATION)); - } - - if (connectorSpec.getConnectorName() == null) { - // Default connector, for compatibility - // It does not make sense to update this for any other connectors. - // We cannot have one definition for additionalConnector[1]/connectorConfiguration and - // different definition for additionalConnector[2]/connectorConfiguration in the object definition. - // The way to go is to set up definitions on the container level. - resourceDefinition.replaceDefinition(ResourceType.F_CONNECTOR_CONFIGURATION, configurationContainerDefinition); - } - - } - - private void evaluateExpression(PrismProperty configurationProperty, PrismObject resource, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException { - PrismPropertyDefinition propDef = configurationProperty.getDefinition(); - String shortDesc = "connector configuration property "+configurationProperty+" in "+resource; - List> extraValues = new ArrayList<>(); - for (PrismPropertyValue configurationPropertyValue: configurationProperty.getValues()) { - ExpressionWrapper expressionWrapper = configurationPropertyValue.getExpression(); - if (expressionWrapper == null) { - return; - } - Object expressionObject = expressionWrapper.getExpression(); - if (!(expressionObject instanceof ExpressionType)) { - throw new IllegalStateException("Expected that expression in "+configurationPropertyValue+" will be ExpressionType, but it was "+expressionObject); - } - ExpressionType expressionType = (ExpressionType) expressionWrapper.getExpression(); - - Expression, PrismPropertyDefinition> expression = expressionFactory.makeExpression(expressionType, propDef, MiscSchemaUtil.getExpressionProfile(), shortDesc, task, result); - ExpressionVariables variables = new ExpressionVariables(); - - // TODO: populate variables - - ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContext(null, variables, shortDesc, task); - PrismValueDeltaSetTriple> expressionOutputTriple = expression.evaluate(expressionContext, - result); - Collection> expressionOutputValues = expressionOutputTriple.getNonNegativeValues(); - if (!expressionOutputValues.isEmpty()) { - Iterator> iterator = expressionOutputValues.iterator(); - PrismPropertyValue firstValue = iterator.next(); - configurationPropertyValue.setValue(firstValue.getValue()); - while (iterator.hasNext()) { - extraValues.add(iterator.next()); - } - } - } - for (PrismPropertyValue extraValue: extraValues) { - configurationProperty.add(extraValue); - } - } - - private ResourceSchema fetchResourceSchema(PrismObject resource, Map> capabilityMap, OperationResult parentResult) - throws CommunicationException, GenericFrameworkException, ConfigurationException, ObjectNotFoundException, SchemaException { - ConnectorSpec connectorSpec = selectConnectorSpec(resource, capabilityMap, SchemaCapabilityType.class); - if (connectorSpec == null) { - LOGGER.debug("No connector has schema capability, cannot fetch resource schema"); - return null; - } - InternalMonitor.recordCount(InternalCounters.RESOURCE_SCHEMA_FETCH_COUNT); - List generateObjectClasses = ResourceTypeUtil.getSchemaGenerationConstraints(resource); - ConnectorInstance connectorInstance = connectorManager.getConfiguredConnectorInstance(connectorSpec, false, parentResult); - - LOGGER.debug("Trying to get schema from {}, objectClasses to generate: {}", connectorSpec, generateObjectClasses); - ResourceSchema resourceSchema = connectorInstance.fetchResourceSchema(parentResult); - - if (ResourceTypeUtil.isValidateSchema(resource.asObjectable())) { - ResourceTypeUtil.validateSchema(resourceSchema, resource); - } - return resourceSchema; - - } - - /** - * Test the connection. - * - * @param resource Resource object as fetched from the repository. Must NOT be immutable! - * - * @throws ObjectNotFoundException If the resource object cannot be found in repository (e.g. when trying to set its - * availability status). - */ - public void testConnection(PrismObject resource, Task task, OperationResult parentResult) - throws ObjectNotFoundException { - - checkMutable(resource); - - String resourceOid = resource.getOid(); - - String operationDesc = "test resource " + resourceOid + "connection"; - - List allConnectorSpecs; - try { - allConnectorSpecs = getAllConnectorSpecs(resource); - } catch (SchemaException e) { - String statusChangeReason = operationDesc + ", getting all connectors failed: " + e.getMessage(); - if (LOGGER.isTraceEnabled()) { - LOGGER.error("Configuration error: {}", e.getMessage(), e); - } - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); - parentResult.recordFatalError("Configuration error: " + e.getMessage(), e); - return; - } - - Map> capabilityMap = new HashMap<>(); - for (ConnectorSpec connectorSpec: allConnectorSpecs) { - - OperationResult connectorTestResult = parentResult - .createSubresult(ConnectorTestOperation.CONNECTOR_TEST.getOperation()); - connectorTestResult.addParam(OperationResult.PARAM_NAME, connectorSpec.getConnectorName()); - connectorTestResult.addParam(OperationResult.PARAM_OID, connectorSpec.getConnectorOid()); - - testConnectionConnector(connectorSpec, capabilityMap, task, connectorTestResult); - - connectorTestResult.computeStatus(); - - if (!connectorTestResult.isAcceptable()) { - //nothing more to do.. if it failed while testing connection, status is set. - // we do not need to continue and waste the time. - return; - } - } - - // === test SCHEMA === - - OperationResult schemaResult = parentResult.createSubresult(ConnectorTestOperation.RESOURCE_SCHEMA.getOperation()); - - ResourceSchema schema; - try { - - schema = fetchResourceSchema(resource, capabilityMap, schemaResult); - - } catch (CommunicationException e) { - String statusChangeReason = operationDesc + " failed while fetching schema: " + e.getMessage(); - if (LOGGER.isTraceEnabled()) { - LOGGER.error("Communication error: {}", e.getMessage(), e); - } - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.DOWN, statusChangeReason, task, parentResult, true); - schemaResult.recordFatalError("Communication error: " + e.getMessage(), e); - return; - } catch (GenericFrameworkException | ConfigurationException | ObjectNotFoundException | SchemaException | RuntimeException e) { - String statusChangeReason = operationDesc + " failed while fetching schema: " + e.getMessage(); - if (LOGGER.isTraceEnabled()) { - LOGGER.error("Error: {}", e.getMessage(), e); - } - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); - schemaResult.recordFatalError("Error: " + e.getMessage(), e); - return; - } - - if (schema == null || schema.isEmpty()) { - // Resource does not support schema - // If there is a static schema in resource definition this may still be OK - try { - schema = RefinedResourceSchemaImpl.getResourceSchema(resource, prismContext); - } catch (SchemaException e) { - String statusChangeReason = operationDesc + " failed while parsing refined schema: " + e.getMessage(); - if (LOGGER.isTraceEnabled()) { - LOGGER.error("Error: {}", e.getMessage(), e); - } - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); - schemaResult.recordFatalError(e); - return; - } - - if (schema == null || schema.isEmpty()) { - String msg = "Connector does not support schema and no static schema available"; - String statusChangeReason = operationDesc + ". " + msg; - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); - schemaResult.recordFatalError(msg); - return; - } - } - - // Invoke completeResource(). This will store the fetched schema to the ResourceType if there is no - // definition already. Therefore the testResource() can be used to generate the resource schema - until we - // have full schema caching capability. - PrismObject completedResource; - try { - // Re-fetching from repository to get up-to-date availability status (to avoid phantom state change records). - PrismObject repoResource = repositoryService.getObject(ResourceType.class, resourceOid, null, schemaResult); - completedResource = completeResourceInternal(repoResource, schema, true, capabilityMap, null, task, schemaResult); - } catch (ObjectNotFoundException e) { - String msg = "Object not found (unexpected error, probably a bug): " + e.getMessage(); - String statusChangeReason = operationDesc + " failed while completing resource. " + msg; - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); - schemaResult.recordFatalError(msg, e); - return; - } catch (SchemaException e) { - String msg = "Schema processing error (probably connector bug): " + e.getMessage(); - String statusChangeReason = operationDesc + " failed while completing resource. " + msg; - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); - schemaResult.recordFatalError(msg, e); - return; - } catch (ExpressionEvaluationException e) { - String msg = "Expression error: " + e.getMessage(); - String statusChangeReason = operationDesc + " failed while completing resource. " + msg; - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); - schemaResult.recordFatalError(msg, e); - return; - } catch (RuntimeException e) { - String msg = "Unspecified exception: " + e.getMessage(); - String statusChangeReason = operationDesc + " failed while completing resource. " + msg; - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); - schemaResult.recordFatalError(msg, e); - return; - } - - schemaResult.recordSuccess(); - - try { - updateResourceSchema(allConnectorSpecs, parentResult, completedResource); - } catch (SchemaException | ObjectNotFoundException | CommunicationException | ConfigurationException | RuntimeException e) { - String statusChangeReason = operationDesc + " failed while updating resource schema: " + e.getMessage(); - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); - parentResult.recordFatalError("Couldn't update resource schema: " + e.getMessage(), e); - return; - } - - // TODO: connector sanity (e.g. refined schema, at least one account type, identifiers - // in schema, etc.) - - } - - private void checkMutable(PrismObject resource) { - if (resource.isImmutable()) { - throw new IllegalArgumentException("Got immutable resource object, while expecting mutable one: " + resource); - } - } - - private void updateResourceSchema(List allConnectorSpecs, OperationResult parentResult, - PrismObject resource) - throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException { - ResourceSchema resourceSchema = RefinedResourceSchemaImpl.getResourceSchema(resource, prismContext); - if (resourceSchema != null) { - for (ConnectorSpec connectorSpec : allConnectorSpecs) { - ConnectorInstance instance = connectorManager.getConfiguredConnectorInstance(connectorSpec, false, parentResult); - instance.updateSchema(resourceSchema); - } - } - } - - private void testConnectionConnector(ConnectorSpec connectorSpec, Map> capabilityMap, Task task, - OperationResult parentResult) throws ObjectNotFoundException { - - // === test INITIALIZATION === - - OperationResult initResult = parentResult - .createSubresult(ConnectorTestOperation.CONNECTOR_INITIALIZATION.getOperation()); - - LOGGER.debug("Testing connection using {}", connectorSpec); - String resourceOid = connectorSpec.getResource().getOid(); - - String operationCtx = "testing connection using " + connectorSpec; - - ConfiguredConnectorInstanceEntry connectorInstanceCacheEntry; - try { - // Make sure we are getting non-configured instance. - connectorInstanceCacheEntry = connectorManager.getConnectorInstanceCacheEntry(connectorSpec, initResult); - initResult.recordSuccess(); - } catch (ObjectNotFoundException e) { - // The connector was not found. The resource definition is either - // wrong or the connector is not installed. - String msg = "The connector was not found: "+e.getMessage(); - operationCtx += " failed while getting connector instance. " + msg; - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); - initResult.recordFatalError(msg, e); - return; - } catch (SchemaException e) { - String msg = "Schema error while dealing with the connector definition: "+e.getMessage(); - operationCtx += " failed while getting connector instance. " + msg; - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); - initResult.recordFatalError(msg, e); - return; - } catch (RuntimeException | Error e) { - String msg = "Unexpected runtime error: "+e.getMessage(); - operationCtx += " failed while getting connector instance. " + msg; - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); - initResult.recordFatalError(msg, e); - return; - } catch (CommunicationException e) { - String msg = "Communication error: "+e.getMessage(); - operationCtx += " failed while getting connector instance. " + msg; - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.DOWN, operationCtx, task, parentResult, true); - initResult.recordFatalError(msg, e); - return; - } catch (ConfigurationException e) { - String msg = "Configuration error: "+e.getMessage(); - operationCtx += " failed while getting connector instance. " + msg; - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); - initResult.recordFatalError(msg, e); - return; - } - - ConnectorInstance connector = connectorInstanceCacheEntry.getConnectorInstance(); - - - // === test CONFIGURATION === - - OperationResult configResult = parentResult - .createSubresult(ConnectorTestOperation.CONNECTOR_CONFIGURATION.getOperation()); - - try { - PrismObject resource = connectorSpec.getResource(); - PrismObjectDefinition newResourceDefinition = resource.getDefinition().clone(); - applyConnectorSchemaToResource(connectorSpec, newResourceDefinition, resource, task, configResult); - PrismContainerValue connectorConfiguration = connectorSpec.getConnectorConfiguration().getValue(); - - InternalMonitor.recordCount(InternalCounters.CONNECTOR_INSTANCE_CONFIGURATION_COUNT); - - connector.configure(connectorConfiguration, ResourceTypeUtil.getSchemaGenerationConstraints(resource), configResult); - - // We need to explicitly initialize the instance, e.g. in case that the schema and capabilities - // cannot be detected by the connector and therefore are provided in the resource - // - // NOTE: the capabilities and schema that are used here are NOT necessarily those that are detected by the resource. - // The detected schema will come later. The schema here is the one that is stored in the resource - // definition (ResourceType). This may be schema that was detected previously. But it may also be a schema - // that was manually defined. This is needed to be passed to the connector in case that the connector - // cannot detect the schema and needs schema/capabilities definition to establish a connection. - // Most connectors will just ignore the schema and capabilities that are provided here. - // But some connectors may need it (e.g. CSV connector working with CSV file without a header). - // - ResourceSchema previousResourceSchema = RefinedResourceSchemaImpl.getResourceSchema(connectorSpec.getResource(), prismContext); - Collection previousCapabilities = ResourceTypeUtil.getNativeCapabilitiesCollection(connectorSpec.getResource().asObjectable()); - connector.initialize(previousResourceSchema, previousCapabilities, - ResourceTypeUtil.isCaseIgnoreAttributeNames(connectorSpec.getResource().asObjectable()), configResult); - - configResult.recordSuccess(); - } catch (CommunicationException e) { - operationCtx += " failed while testing configuration: " + e.getMessage(); - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.DOWN, operationCtx, task, parentResult, true); - configResult.recordFatalError("Communication error", e); - return; - } catch (GenericFrameworkException e) { - operationCtx += " failed while testing configuration: " + e.getMessage(); - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); - configResult.recordFatalError("Generic error", e); - return; - } catch (SchemaException e) { - operationCtx += " failed while testing configuration: " + e.getMessage(); - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); - configResult.recordFatalError("Schema error", e); - return; - } catch (ConfigurationException e) { - operationCtx += " failed while testing configuration: " + e.getMessage(); - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); - configResult.recordFatalError("Configuration error", e); - return; - } catch (ObjectNotFoundException e) { - operationCtx += " failed while testing configuration: " + e.getMessage(); - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); - configResult.recordFatalError("Object not found", e); - return; - } catch (ExpressionEvaluationException e) { - operationCtx += " failed while testing configuration: " + e.getMessage(); - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); - configResult.recordFatalError("Expression error", e); - return; - } catch (SecurityViolationException e) { - operationCtx += " failed while testing configuration: " + e.getMessage(); - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); - configResult.recordFatalError("Security violation", e); - return; - } catch (RuntimeException | Error e) { - operationCtx += " failed while testing configuration: " + e.getMessage(); - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); - configResult.recordFatalError("Unexpected runtime error", e); - return; - } - - // === test CONNECTION === - - // delegate the main part of the test to the connector - connector.test(parentResult); - - parentResult.computeStatus(); - if (!parentResult.isAcceptable()) { - operationCtx += ". Connector test failed: " + parentResult.getMessage(); - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.DOWN, operationCtx, task, parentResult, true); - // No point in going on. Following tests will fail anyway, they will - // just produce misleading - // messages. - return; - } else { - operationCtx += ". Connector test successful."; - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.UP, operationCtx, task, parentResult, false); - } - - // === test CAPABILITIES === - - OperationResult capabilitiesResult = parentResult - .createSubresult(ConnectorTestOperation.CONNECTOR_CAPABILITIES.getOperation()); - try { - InternalMonitor.recordCount(InternalCounters.CONNECTOR_CAPABILITIES_FETCH_COUNT); - Collection retrievedCapabilities = connector.fetchCapabilities(capabilitiesResult); - - capabilityMap.put(connectorSpec.getConnectorName(), retrievedCapabilities); - capabilitiesResult.recordSuccess(); - } catch (CommunicationException e) { - operationCtx += " failed while testing capabilities: " + e.getMessage(); - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.DOWN, operationCtx, task, parentResult, true); - capabilitiesResult.recordFatalError("Communication error", e); - return; - } catch (GenericFrameworkException e) { - operationCtx += " failed while testing capabilities: " + e.getMessage(); - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); - capabilitiesResult.recordFatalError("Generic error", e); - return; - } catch (ConfigurationException e) { - operationCtx += " failed while testing capabilities: " + e.getMessage(); - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); - capabilitiesResult.recordFatalError("Configuration error", e); - return; - } catch (SchemaException e) { - operationCtx += " failed while testing capabilities: " + e.getMessage(); - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); - capabilitiesResult.recordFatalError("Schema error", e); - return; - } catch (RuntimeException | Error e) { - operationCtx += " failed while testing capabilities: " + e.getMessage(); - modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); - capabilitiesResult.recordFatalError("Unexpected runtime error", e); - return; - } - - // Connector instance is fully configured at this point. - // But the connector cache entry may not be set up properly and it is not yet placed into the cache. - // Therefore make sure the caching bit is completed. - // Place the connector to cache even if it was configured at the beginning. The connector is reconfigured now. - connectorManager.cacheConfiguredConnector(connectorInstanceCacheEntry, connectorSpec); - } - - /** - * Modifies resource availability status in the repository (if needed). - * - * The necessity of status modification is determined against the current version of the resource - unless "skipGetResource" - * is set. The resource is hopefully cached ResourceCache, so the performance impact should be almost ponone. - * - * Also note that in-memory representation of the resource is not modified. As a side effect, the cached resource - * is invalidated because of the modification. But it will be loaded on the next occasion. This should be quite harmless, - * as we do not expect availability changes to occur frequently. - * - * @param statusChangeReason Description of the reason of changing the availability status. - * @param skipGetResource True if we want to skip "getResource" operation and therefore apply the change regardless of - * the current resource availability status. This is to be used in situations where we expect that - * the resource might not be successfully retrievable (e.g. if it's broken). - * - * @throws ObjectNotFoundException If the resource object does not exist in repository. - */ - public void modifyResourceAvailabilityStatus(String resourceOid, AvailabilityStatusType newStatus, String statusChangeReason, - Task task, OperationResult result, boolean skipGetResource) throws ObjectNotFoundException { - - AvailabilityStatusType currentStatus; - String resourceDesc; - PrismObject resource; - if (skipGetResource) { - resource = null; - currentStatus = null; - resourceDesc = "resource " + resourceOid; - } else { - try { - resource = getResource(resourceOid, GetOperationOptions.createNoFetch(), task, result); - } catch (SchemaException | ExpressionEvaluationException e) { - // We actually do not expect any of these exceptions here. The resource is most probably in use - result.recordFatalError("Unexpected exception: " + e.getMessage(), e); - throw new SystemException("Unexpected exception: " + e.getMessage(), e); - } - ResourceType resourceBean = resource.asObjectable(); - currentStatus = ResourceTypeUtil.getLastAvailabilityStatus(resourceBean); - resourceDesc = resource.toString(); - } - - if (newStatus != currentStatus) { - try { - List> modifications = operationalStateManager.createAndLogOperationalStateDeltas(currentStatus, newStatus, - resourceDesc, statusChangeReason, resource); - repositoryService.modifyObject(ResourceType.class, resourceOid, modifications, result); - result.computeStatusIfUnknown(); - InternalMonitor.recordCount(InternalCounters.RESOURCE_REPOSITORY_MODIFY_COUNT); - } catch (SchemaException | ObjectAlreadyExistsException e) { - throw new SystemException("Unexpected exception while recording operation state change: " + e.getMessage(), e); - } - } - } - - /** - * Adjust scheme with respect to capabilities. E.g. disable attributes that - * are used for special purpose (such as account activation simulation). - * - * TODO treat also objectclass-specific capabilities here - */ - private void adjustSchemaForSimulatedCapabilities(PrismObject resource, ResourceSchema resourceSchema) { - ResourceType resourceType = resource.asObjectable(); - if (resourceType.getCapabilities() == null || resourceType.getCapabilities().getConfigured() == null) { - return; - } - ActivationCapabilityType activationCapability = CapabilityUtil.getCapability(resourceType - .getCapabilities().getConfigured().getAny(), ActivationCapabilityType.class); - if (CapabilityUtil.getEffectiveActivationStatus(activationCapability) != null) { - QName attributeName = activationCapability.getStatus().getAttribute(); - Boolean ignore = activationCapability.getStatus().isIgnoreAttribute(); - if (attributeName != null) { - // The attribute used for enable/disable simulation should be ignored in the schema - // otherwise strange things may happen, such as changing the same attribute both from - // activation/enable and from the attribute using its native name. - for (ObjectClassComplexTypeDefinition objectClassDefinition : resourceSchema - .getDefinitions(ObjectClassComplexTypeDefinition.class)) { - ResourceAttributeDefinition attributeDefinition = objectClassDefinition - .findAttributeDefinition(attributeName); - if (attributeDefinition != null) { - if (ignore == null || ignore) { - ((MutableItemDefinition) attributeDefinition).setProcessing(ItemProcessing.IGNORE); - } - } else { - // simulated activation attribute points to something that is not in the schema - // technically, this is an error. But it looks to be quite common in connectors. - // The enable/disable is using operational attributes that are not exposed in the - // schema, but they work if passed to the connector. - // Therefore we don't want to break anything. We could log an warning here, but the - // warning would be quite frequent. Maybe a better place to warn user would be import - // of the object. - LOGGER.debug("Simulated activation attribute " - + attributeName - + " for objectclass " - + objectClassDefinition.getTypeName() - + " in " - + resource - + " does not exist in the resource schema. This may work well, but it is not clean. Connector exposing such schema should be fixed."); - } - } - } - } - } - - // TODO should this one be used? - private void checkSchema(PrismSchema schema) throws SchemaException { - // This is resource schema, it should contain only - // ResourceObjectDefinitions - for (Definition def : schema.getDefinitions()) { - if (def instanceof ComplexTypeDefinition) { - // This is OK - } else if (def instanceof ResourceAttributeContainerDefinition) { - checkResourceObjectDefinition((ResourceAttributeContainerDefinition) def); - } else { - throw new SchemaException("Unexpected definition in resource schema: " + def); - } - } - } - - private void checkResourceObjectDefinition(ResourceAttributeContainerDefinition rod) - throws SchemaException { - for (ItemDefinition def : rod.getDefinitions()) { - if (!(def instanceof ResourceAttributeDefinition)) { - throw new SchemaException("Unexpected definition in resource schema object " + rod + ": " - + def); - } - } - } - - public void applyDefinition(ObjectDelta delta, ResourceType resourceWhenNoOid, GetOperationOptions options, Task task, OperationResult objectResult) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException { - - if (delta.isAdd()) { - PrismObject resource = delta.getObjectToAdd(); - applyConnectorSchemasToResource(resource, task, objectResult); - return; - - } else if (delta.isModify()) { - // Go on - } else { - return; - } - - if (delta.hasCompleteDefinition()){ - //nothing to do, all modifications has definitions..just aplly this deltas.. - return; - } - - - PrismObject resource; - String resourceOid = delta.getOid(); - if (resourceOid == null) { - Validate.notNull(resourceWhenNoOid, "Resource oid not specified in the object delta, and resource is not specified as well. Could not apply definition."); - resource = resourceWhenNoOid.asPrismObject(); - } else { - resource = getResource(resourceOid, options, task, objectResult); - } - - ResourceType resourceType = resource.asObjectable(); -// ResourceType resourceType = completeResource(resource.asObjectable(), null, objectResult); - //TODO TODO TODO FIXME FIXME FIXME copied from ObjectImprted..union this two cases - PrismContainer configurationContainer = ResourceTypeUtil.getConfigurationContainer(resourceType); - if (configurationContainer == null || configurationContainer.isEmpty()) { - // Nothing to check - objectResult.recordWarning("The resource has no configuration"); - return; - } - - // Check the resource configuration. The schema is in connector, so fetch the connector first - String connectorOid = resourceType.getConnectorRef().getOid(); - if (StringUtils.isBlank(connectorOid)) { - objectResult.recordFatalError("The connector reference (connectorRef) is null or empty"); - return; - } - - //ItemDelta.findItemDelta(delta.getModifications(), ResourceType.F_SCHEMA, ContainerDelta.class) == null || - - ReferenceDelta connectorRefDelta = ItemDeltaCollectionsUtil.findReferenceModification(delta.getModifications(), ResourceType.F_CONNECTOR_REF); - if (connectorRefDelta != null){ - Item connectorRefNew = connectorRefDelta.getItemNewMatchingPath(null); - if (connectorRefNew.getValues().size() == 1){ - PrismReferenceValue connectorRefValue = connectorRefNew.getValues().iterator().next(); - if (connectorRefValue.getOid() != null && !connectorOid.equals(connectorRefValue.getOid())){ - connectorOid = connectorRefValue.getOid(); - } - } - } - - PrismObject connector; - ConnectorType connectorType; - try { - connector = repositoryService.getObject(ConnectorType.class, connectorOid, null, objectResult); - connectorType = connector.asObjectable(); - } catch (ObjectNotFoundException e) { - // No connector, no fun. We can't check the schema. But this is referential integrity problem. - // Mark the error ... there is nothing more to do - objectResult.recordFatalError("Connector (OID:" + connectorOid + ") referenced from the resource is not in the repository", e); - return; - } catch (SchemaException e) { - // Probably a malformed connector. To be kind of robust, lets allow the import. - // Mark the error ... there is nothing more to do - objectResult.recordPartialError("Connector (OID:" + connectorOid + ") referenced from the resource has schema problems: " + e.getMessage(), e); - LOGGER.error("Connector (OID:{}) referenced from the imported resource \"{}\" has schema problems: {}-{}", - connectorOid, resourceType.getName(), e.getMessage(), e); - return; - } - - Element connectorSchemaElement = ConnectorTypeUtil.getConnectorXsdSchema(connector); - MutablePrismSchema connectorSchema; - if (connectorSchemaElement == null) { - // No schema to validate with - return; - } - try { - connectorSchema = prismContext.schemaFactory().createPrismSchema(DOMUtil.getSchemaTargetNamespace(connectorSchemaElement)); - connectorSchema.parseThis(connectorSchemaElement, true, "schema for " + connector, prismContext); - } catch (SchemaException e) { - objectResult.recordFatalError("Error parsing connector schema for " + connector + ": "+e.getMessage(), e); - return; - } - QName configContainerQName = new QName(connectorType.getNamespace(), ResourceType.F_CONNECTOR_CONFIGURATION.getLocalPart()); - PrismContainerDefinition configContainerDef = - connectorSchema.findContainerDefinitionByElementName(configContainerQName); - if (configContainerDef == null) { - objectResult.recordFatalError("Definition of configuration container " + configContainerQName + " not found in the schema of of " + connector); - return; - } - - try { - configurationContainer.applyDefinition(configContainerDef); - } catch (SchemaException e) { - objectResult.recordFatalError("Configuration error in " + resource + ": "+e.getMessage(), e); - return; - } - - PrismContainer configContainer = resourceType.asPrismObject().findContainer(ResourceType.F_CONNECTOR_CONFIGURATION); - //noinspection unchecked - configContainer.applyDefinition(configContainerDef); - - for (ItemDelta itemDelta : delta.getModifications()){ - applyItemDefinition(itemDelta, configContainerDef, objectResult); - } - } - - private void applyItemDefinition(ItemDelta itemDelta, - PrismContainerDefinition configContainerDef, OperationResult objectResult) throws SchemaException { - if (itemDelta.getParentPath() == null){ - LOGGER.trace("No parent path defined for item delta {}", itemDelta); - return; - } - - QName first = itemDelta.getParentPath().firstToNameOrNull(); - if (first == null) { - return; - } - - if (itemDelta.getDefinition() == null && (ResourceType.F_CONNECTOR_CONFIGURATION.equals(first) || ResourceType.F_SCHEMA.equals(first))){ - ItemPath path = itemDelta.getPath().rest(); - D itemDef = configContainerDef.findItemDefinition(path); - if (itemDef == null){ - LOGGER.warn("No definition found for item {}. Check your namespaces?", path); - objectResult.recordWarning("No definition found for item delta: " + itemDelta +". Check your namespaces?" ); -// throw new SchemaException("No definition found for item " + path+ ". Check your namespaces?" ); - return; - } - itemDelta.applyDefinition(itemDef); - - } - } - - public void applyDefinition(PrismObject resource, Task task, OperationResult parentResult) - throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException { - applyConnectorSchemasToResource(resource, task, parentResult); - } - - public void applyDefinition(ObjectQuery query, OperationResult result) { - // TODO: not implemented yet - } - - public Object executeScript(String resourceOid, ProvisioningScriptType script, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException { - PrismObject resource = getResource(resourceOid, null, task, result); - ConnectorSpec connectorSpec = selectConnectorSpec(resource, ScriptCapabilityType.class); - if (connectorSpec == null) { - throw new UnsupportedOperationException("No connector supports script capability"); - } - ConnectorInstance connectorInstance = connectorManager.getConfiguredConnectorInstance(connectorSpec, false, result); - ExecuteProvisioningScriptOperation scriptOperation = ProvisioningUtil.convertToScriptOperation(script, "script on "+resource, prismContext); - try { - StateReporter reporter = new StateReporter(resourceOid, task); - return connectorInstance.executeScript(scriptOperation, reporter, result); - } catch (GenericFrameworkException e) { - // Not expected. Transform to system exception - result.recordFatalError("Generic provisioning framework error", e); - throw new SystemException("Generic provisioning framework error: " + e.getMessage(), e); - } - } - - public List getConnectorOperationalStatus(PrismObject resource, OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { - List statuses = new ArrayList<>(); - for (ConnectorSpec connectorSpec: getAllConnectorSpecs(resource)) { - ConnectorInstance connectorInstance = connectorManager.getConfiguredConnectorInstance(connectorSpec, false, result); - ConnectorOperationalStatus operationalStatus = connectorInstance.getOperationalStatus(); - if (operationalStatus != null) { - operationalStatus.setConnectorName(connectorSpec.getConnectorName()); - statuses.add(operationalStatus); - } - } - return statuses; - } - - private List getAllConnectorSpecs(PrismObject resource) throws SchemaException { - List connectorSpecs = new ArrayList<>(); - connectorSpecs.add(getDefaultConnectorSpec(resource)); - for (ConnectorInstanceSpecificationType additionalConnectorType: resource.asObjectable().getAdditionalConnector()) { - connectorSpecs.add(getConnectorSpec(resource, additionalConnectorType)); - } - return connectorSpecs; - } - - // Should be used only internally (private). But it is public, because it is accessed from the tests. - public ConnectorInstance getConfiguredConnectorInstance(PrismObject resource, - Class operationCapabilityClass, boolean forceFresh, OperationResult parentResult) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException { - ConnectorSpec connectorSpec = selectConnectorSpec(resource, operationCapabilityClass); - if (connectorSpec == null) { - return null; - } - return connectorManager.getConfiguredConnectorInstance(connectorSpec, forceFresh, parentResult); - } - - // Used by the tests. Does not change anything. - ConnectorInstance getConfiguredConnectorInstanceFromCache(PrismObject resource, - Class operationCapabilityClass) throws SchemaException { - ConnectorSpec connectorSpec = selectConnectorSpec(resource, operationCapabilityClass); - return connectorSpec != null ? connectorManager.getConfiguredConnectorInstanceFromCache(connectorSpec) : null; - } - - public CapabilitiesType getConnectorCapabilities(ResourceType resource, - RefinedObjectClassDefinition objectClassDefinition, Class operationCapabilityClass) { - if (resource == null) { - return null; - } - - CapabilitiesType connectorCapabilities = null; - for (ConnectorInstanceSpecificationType additionalConnectorType : resource.getAdditionalConnector()) { - if (supportsCapability(additionalConnectorType, operationCapabilityClass)) { - connectorCapabilities = additionalConnectorType.getCapabilities(); - } - } - - if (connectorCapabilities == null) { - connectorCapabilities = resource.getCapabilities(); - } - - - CapabilitiesType finalCapabilities = applyObjectClassCapabilities(connectorCapabilities, objectClassDefinition); - LOGGER.trace("Returning final capabilities:\n{} ", finalCapabilities); - return finalCapabilities; - - } - - private CapabilitiesType applyObjectClassCapabilities(CapabilitiesType connectorCapabilities, RefinedObjectClassDefinition objectClassDefinition) { - - if (objectClassDefinition == null) { - return connectorCapabilities; - } - - CapabilitiesType objectClassCapabilities = objectClassDefinition.getCapabilities(); - if (objectClassCapabilities == null) { - LOGGER.trace("No capabilities for {} specified, skipping merge.", objectClassDefinition); - return connectorCapabilities; - } - - CapabilityCollectionType configured = objectClassCapabilities.getConfigured(); - if (configured == null) { - LOGGER.trace("Empty capabilities in {} specified, skipping merge", objectClassDefinition); - return connectorCapabilities; - } - - CapabilitiesType finalCapabilities = new CapabilitiesType(); - if (connectorCapabilities.getNative() != null) { - finalCapabilities.setNative(connectorCapabilities.getNative()); - } - - if (!hasConfiguredCapabilities(connectorCapabilities)) { - LOGGER.trace("No configured capabilities found for connector, replacing with capabilities defined for {}", objectClassDefinition); - finalCapabilities.setConfigured(configured); - return finalCapabilities; - } - - for (Object capability : connectorCapabilities.getConfigured().getAny()) { - - if (!CapabilityUtil.containsCapabilityWithSameElementName(configured.getAny(), capability)) { - configured.getAny().add(capability); - } - } - - finalCapabilities.setConfigured(configured); - return finalCapabilities; - } - - private boolean hasConfiguredCapabilities(CapabilitiesType supportedCapabilities) { - CapabilityCollectionType configured = supportedCapabilities.getConfigured(); - return configured != null && !configured.getAny().isEmpty(); - } - - private ConnectorSpec selectConnectorSpec(PrismObject resource, Map> capabilityMap, Class capabilityClass) throws SchemaException { - if (capabilityMap == null) { - return selectConnectorSpec(resource, capabilityClass); - } - for (ConnectorInstanceSpecificationType additionalConnectorType: resource.asObjectable().getAdditionalConnector()) { - if (supportsCapability(additionalConnectorType, capabilityMap.get(additionalConnectorType.getName()), capabilityClass)) { - return getConnectorSpec(resource, additionalConnectorType); - } - } - return getDefaultConnectorSpec(resource); - } - - private ConnectorSpec selectConnectorSpec(PrismObject resource, Class operationCapabilityClass) throws SchemaException { - for (ConnectorInstanceSpecificationType additionalConnectorType: resource.asObjectable().getAdditionalConnector()) { - if (supportsCapability(additionalConnectorType, operationCapabilityClass)) { - return getConnectorSpec(resource, additionalConnectorType); - } - } - return getDefaultConnectorSpec(resource); - } - - private boolean supportsCapability(ConnectorInstanceSpecificationType additionalConnectorType, Class capabilityClass) { - T cap = CapabilityUtil.getEffectiveCapability(additionalConnectorType.getCapabilities(), capabilityClass); - if (cap == null) { - return false; - } - return CapabilityUtil.isCapabilityEnabled(cap); - } - - private boolean supportsCapability(ConnectorInstanceSpecificationType additionalConnectorType, Collection nativeCapabilities, Class capabilityClass) { - CapabilitiesType specifiedCapabilitiesType = additionalConnectorType.getCapabilities(); - if (specifiedCapabilitiesType != null) { - CapabilityCollectionType configuredCapCollectionType = specifiedCapabilitiesType.getConfigured(); - if (configuredCapCollectionType != null) { - T configuredCap = CapabilityUtil.getCapability(configuredCapCollectionType.getAny(), capabilityClass); - if (configuredCap != null && !CapabilityUtil.isCapabilityEnabled(configuredCap)) { - return false; - } - } - - } - T cap = CapabilityUtil.getCapability(nativeCapabilities, capabilityClass); - if (cap == null) { - return false; - } - return CapabilityUtil.isCapabilityEnabled(cap); - } - - private ConnectorSpec getDefaultConnectorSpec(PrismObject resource) { - PrismContainer connectorConfiguration = resource.findContainer(ResourceType.F_CONNECTOR_CONFIGURATION); - return new ConnectorSpec(resource, null, ResourceTypeUtil.getConnectorOid(resource), connectorConfiguration); - } - - private ConnectorSpec getConnectorSpec(PrismObject resource, ConnectorInstanceSpecificationType additionalConnectorType) throws SchemaException { - if (additionalConnectorType.getConnectorRef() == null) { - throw new SchemaException("No connector reference in additional connector in "+resource); - } - String connectorOid = additionalConnectorType.getConnectorRef().getOid(); - if (StringUtils.isBlank(connectorOid)) { - throw new SchemaException("No connector OID in additional connector in "+resource); - } - //noinspection unchecked - PrismContainer connectorConfiguration = additionalConnectorType.asPrismContainerValue().findContainer(ConnectorInstanceSpecificationType.F_CONNECTOR_CONFIGURATION); - String connectorName = additionalConnectorType.getName(); - if (StringUtils.isBlank(connectorName)) { - throw new SchemaException("No connector name in additional connector in "+resource); - } - return new ConnectorSpec(resource, connectorName, connectorOid, connectorConfiguration); - } - - public PrismContext getPrismContext() { - return prismContext; - } -} +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.provisioning.impl; + +import java.util.*; + +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; +import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.delta.*; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.schema.MutablePrismSchema; +import com.evolveum.midpoint.schema.processor.*; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import com.evolveum.prism.xml.ns._public.types_3.SchemaDefinitionType; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.Validate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.schema.PrismSchema; +import com.evolveum.midpoint.provisioning.api.GenericConnectorException; +import com.evolveum.midpoint.provisioning.ucf.api.ConnectorInstance; +import com.evolveum.midpoint.provisioning.ucf.api.ExecuteProvisioningScriptOperation; +import com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException; +import com.evolveum.midpoint.provisioning.util.ProvisioningUtil; +import com.evolveum.midpoint.repo.api.RepositoryService; +import com.evolveum.midpoint.repo.common.expression.Expression; +import com.evolveum.midpoint.repo.common.expression.ExpressionEvaluationContext; +import com.evolveum.midpoint.repo.common.expression.ExpressionFactory; +import com.evolveum.midpoint.repo.common.expression.ExpressionVariables; +import com.evolveum.midpoint.schema.CapabilityUtil; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.constants.ConnectorTestOperation; +import com.evolveum.midpoint.schema.internals.InternalCounters; +import com.evolveum.midpoint.schema.internals.InternalMonitor; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.statistics.ConnectorOperationalStatus; +import com.evolveum.midpoint.schema.util.ConnectorTypeUtil; +import com.evolveum.midpoint.schema.util.MiscSchemaUtil; +import com.evolveum.midpoint.schema.util.ObjectTypeUtil; +import com.evolveum.midpoint.schema.util.ResourceTypeUtil; +import com.evolveum.midpoint.task.api.StateReporter; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.DOMUtil; +import com.evolveum.midpoint.util.DebugUtil; +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.util.exception.SystemException; +import com.evolveum.midpoint.util.exception.TunnelException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationCapabilityType; +import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.CapabilityType; +import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.SchemaCapabilityType; +import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ScriptCapabilityType; + +@Component +public class ResourceManager { + + @Autowired @Qualifier("cacheRepositoryService") + private RepositoryService repositoryService; + + @Autowired private ResourceCache resourceCache; + @Autowired private ConnectorManager connectorManager; + @Autowired private PrismContext prismContext; + @Autowired private ExpressionFactory expressionFactory; + @Autowired private ResourceOperationalStateManager operationalStateManager; + + private static final Trace LOGGER = TraceManager.getTrace(ResourceManager.class); + + private static final String OP_COMPLETE_RESOURCE = ResourceManager.class.getName() + ".completeResource"; + + /** + * Completes a resource that has been - we expect - just retrieved from the repository, usually by a search operation. + */ + PrismObject completeResource(PrismObject repositoryObject, GetOperationOptions options, Task task, + OperationResult parentResult) + throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException { + + String oid = repositoryObject.getOid(); + boolean readonly = GetOperationOptions.isReadOnly(options); + + PrismObject cachedResource = resourceCache.get(oid, repositoryObject.getVersion(), readonly); + if (cachedResource != null) { + return cachedResource; + } else { + LOGGER.debug("Storing fetched resource {}, version {} to cache (previously cached version {})", + oid, repositoryObject.getVersion(), resourceCache.getVersion(oid)); + PrismObject mutableRepositoryObject = repositoryObject.cloneIfImmutable(); + return completeAndCacheResource(mutableRepositoryObject, options, task, parentResult); + } + } + + /** + * Gets a resource. + */ + public PrismObject getResource(String oid, GetOperationOptions options, Task task, OperationResult parentResult) + throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException { + boolean readonly = GetOperationOptions.isReadOnly(options); + PrismObject cachedResource = resourceCache.getIfLatest(oid, readonly, parentResult); + if (cachedResource != null) { + LOGGER.trace("Returning resource from cache:\n{}", cachedResource.debugDumpLazily()); + return cachedResource; + } else { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Fetching resource {} and storing to cache (previously cached version {}) (options={})", + oid, resourceCache.getVersion(oid), options); + } + // We must obviously NOT fetch resource from repo as read-only. We are going to modify it. + PrismObject repositoryObject = readResourceFromRepository(oid, parentResult); + return completeAndCacheResource(repositoryObject, options, task, parentResult); + } + } + + private PrismObject readResourceFromRepository(String oid, OperationResult parentResult) + throws ObjectNotFoundException, SchemaException { + InternalMonitor.recordCount(InternalCounters.RESOURCE_REPOSITORY_READ_COUNT); + return repositoryService.getObject(ResourceType.class, oid, null, parentResult); + } + + /** + * Here we complete the resource and cache it. + * + * @param repositoryObject Up-to-date repository object. Must be mutable. + */ + private PrismObject completeAndCacheResource(PrismObject repositoryObject, + GetOperationOptions options, Task task, OperationResult parentResult) + throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException { + + checkMutable(repositoryObject); + + PrismObject completedResource = completeResourceInternal(repositoryObject, null, + false, null, options, task, parentResult); + + logResourceAfterCompletion(completedResource); + if (!isComplete(completedResource)) { + // No not cache non-complete resources (e.g. those retrieved with noFetch) + LOGGER.debug("Not putting {} into cache because it's not complete", repositoryObject); + } else { + OperationResult completeResourceResult = parentResult.findSubresult(OP_COMPLETE_RESOURCE); + if (!completeResourceResult.isSuccess()) { + LOGGER.debug("Not putting {} into cache because the completeResource operation status is {}", + ObjectTypeUtil.toShortString(repositoryObject), completeResourceResult.getStatus()); + } else { + LOGGER.debug("Putting {} into cache", repositoryObject); + // Cache only resources that are completely OK + resourceCache.put(completedResource); + } + } + return completedResource; + } + + private void logResourceAfterCompletion(PrismObject completedResource) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Resource after completion, before putting into cache:\n{}", completedResource.debugDump()); + Element xsdSchemaElement = ResourceTypeUtil.getResourceXsdSchema(completedResource); + if (xsdSchemaElement == null) { + LOGGER.trace("Schema: null"); + } else { + LOGGER.trace("Schema:\n{}", + DOMUtil.serializeDOMToString(ResourceTypeUtil.getResourceXsdSchema(completedResource))); + } + } + } + + void deleteResource(String oid, OperationResult parentResult) throws ObjectNotFoundException { + resourceCache.remove(oid); + repositoryService.deleteObject(ResourceType.class, oid, parentResult); + } + + /** + * Make sure that the resource is complete. + * + * It will check if the resource has a sufficiently fresh schema, etc. + * + * Returned resource may be the same or may be a different instance, but it + * is guaranteed that it will be "fresher" and will correspond to the + * repository state (assuming that the provided resource also corresponded + * to the repository state). + * + * The connector schema that was fetched before can be supplied to this + * method. This is just an optimization. It comes handy e.g. in test + * connection case. + * + * Note: This is not really the best place for this method. Need to figure + * out correct place later. + * + * @param repoResource + * Resource to check + * @param resourceSchema + * schema that was freshly pre-fetched (or null) + * + * @return completed resource + */ + private PrismObject completeResourceInternal(PrismObject repoResource, ResourceSchema resourceSchema, + boolean fetchedSchema, Map> capabilityMap, GetOperationOptions options, Task task, OperationResult parentResult) + throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException { + + checkMutable(repoResource); + + OperationResult result = parentResult.createMinorSubresult(OP_COMPLETE_RESOURCE); + try { + try { + applyConnectorSchemasToResource(repoResource, task, result); + } catch (Throwable t) { + String message = + "An error occurred while applying connector schema to connector configuration of " + repoResource + ": " + + t.getMessage(); + result.recordPartialError(message, t); + LOGGER.warn(message, t); + return repoResource; + } + + PrismObject newResource; + + if (isComplete(repoResource)) { + // The resource is complete. + newResource = repoResource; + + } else { + // The resource is NOT complete. Try to fetch schema and capabilities + + if (GetOperationOptions.isNoFetch(options)) { + // We need to fetch schema, but the noFetch option is specified. Therefore return whatever we have. + result.recordSuccessIfUnknown(); + return repoResource; + } + + try { + + completeSchemaAndCapabilities(repoResource, resourceSchema, fetchedSchema, capabilityMap, result); + + } catch (Exception ex) { + // Catch the exceptions. There are not critical. We need to catch them all because the connector may + // throw even undocumented runtime exceptions. + // Even non-complete resource may still be usable. The fetchResult indicates that there was an error + result.recordPartialError("Cannot complete resource schema and capabilities: " + ex.getMessage(), ex); + return repoResource; + } + + try { + // Now we need to re-read the resource from the repository and re-apply the schemas. This ensures that we will + // cache the correct version and that we avoid race conditions, etc. + + newResource = readResourceFromRepository(repoResource.getOid(), result); + applyConnectorSchemasToResource(newResource, task, result); + + } catch (SchemaException | ObjectNotFoundException | RuntimeException e) { + result.recordFatalError(e); + throw e; + } + } + + try { + // make sure it has parsed resource and refined schema. We are going to cache + // it, so we want to cache it with the parsed schemas + RefinedResourceSchemaImpl.getResourceSchema(newResource, prismContext); + RefinedResourceSchemaImpl.getRefinedSchema(newResource); + + } catch (SchemaException e) { + String message = "Schema error while processing schemaHandling section of " + newResource + ": " + e.getMessage(); + result.recordPartialError(message, e); + LOGGER.warn(message, e); + return newResource; + } catch (RuntimeException e) { + String message = + "Unexpected error while processing schemaHandling section of " + newResource + ": " + e.getMessage(); + result.recordPartialError(message, e); + LOGGER.warn(message, e); + return newResource; + } + + result.recordSuccessIfUnknown(); + + return newResource; + } catch (Throwable t) { + result.recordFatalError(t); + throw t; + } finally { + result.computeStatusIfUnknown(); + } + } + + private boolean isComplete(PrismObject resource) { + ResourceType resourceType = resource.asObjectable(); + if (ResourceTypeUtil.getResourceXsdSchema(resource) == null) { + return false; + } + CapabilitiesType capabilitiesType = resourceType.getCapabilities(); + return capabilitiesType != null && capabilitiesType.getCachingMetadata() != null; + } + + + private void completeSchemaAndCapabilities(PrismObject resource, ResourceSchema resourceSchema, boolean fetchedSchema, + Map> capabilityMap, OperationResult result) + throws SchemaException, CommunicationException, ObjectNotFoundException, GenericFrameworkException, ConfigurationException { + + Collection> modifications = new ArrayList<>(); + + // Capabilities + // we need to process capabilities first. Schema is one of the connector capabilities. + // We need to determine this capability to select the right connector for schema retrieval. + completeCapabilities(resource, capabilityMap != null, capabilityMap, modifications, result); + + if (resourceSchema == null) { + // Try to get existing schema from resource. We do not want to override this if it exists + // (but we still want to refresh the capabilities, that happens below) + resourceSchema = RefinedResourceSchemaImpl.getResourceSchema(resource, prismContext); + } + + if (resourceSchema == null || resourceSchema.isEmpty()) { + + LOGGER.trace("Fetching resource schema for {}", resource); + + resourceSchema = fetchResourceSchema(resource, capabilityMap, result); + + if (resourceSchema == null) { + LOGGER.warn("No resource schema fetched from {}", resource); + } else if (resourceSchema.isEmpty()) { + LOGGER.warn("Empty resource schema fetched from {}", resource); + } else { + LOGGER.debug("Fetched resource schema for {}: {} definitions", resource, resourceSchema.getDefinitions().size()); + fetchedSchema = true; + } + } + + if (resourceSchema != null) { + if (fetchedSchema) { + adjustSchemaForSimulatedCapabilities(resource, resourceSchema); + modifications.add(createSchemaUpdateDelta(resource, resourceSchema)); + AvailabilityStatusType previousStatus = ResourceTypeUtil.getLastAvailabilityStatus(resource.asObjectable()); + if (previousStatus != AvailabilityStatusType.UP) { + modifications.addAll(operationalStateManager.createAndLogOperationalStateDeltas(previousStatus, + AvailabilityStatusType.UP, resource.toString(), + "resource schema was successfully fetched", resource)); + } else { + // just for sure (if the status changed in the meanwhile) + modifications.add(operationalStateManager.createAvailabilityStatusDelta(AvailabilityStatusType.UP)); + } + } else { + CachingMetadataType schemaCachingMetadata = resource.asObjectable().getSchema().getCachingMetadata(); + if (schemaCachingMetadata == null) { + schemaCachingMetadata = MiscSchemaUtil.generateCachingMetadata(); + modifications.add( + prismContext.deltaFactory().property().createModificationReplaceProperty( + ItemPath.create(ResourceType.F_SCHEMA, CapabilitiesType.F_CACHING_METADATA), + resource.getDefinition(), + schemaCachingMetadata) + ); + } + } + } + + if (!modifications.isEmpty()) { + try { + LOGGER.trace("Completing {}:\n{}", resource, DebugUtil.debugDumpLazily(modifications, 1)); + repositoryService.modifyObject(ResourceType.class, resource.getOid(), modifications, result); + InternalMonitor.recordCount(InternalCounters.RESOURCE_REPOSITORY_MODIFY_COUNT); + } catch (ObjectAlreadyExistsException ex) { + // This should not happen + throw new SystemException(ex); + } + } + } + + private void completeCapabilities(PrismObject resource, boolean forceRefresh, Map> capabilityMap, Collection> modifications, + OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException { + ResourceType resourceType = resource.asObjectable(); + ConnectorSpec defaultConnectorSpec = getDefaultConnectorSpec(resource); + CapabilitiesType resourceCapType = resourceType.getCapabilities(); + if (resourceCapType == null) { + resourceCapType = new CapabilitiesType(); + resourceType.setCapabilities(resourceCapType); + } + completeConnectorCapabilities(defaultConnectorSpec, resourceCapType, ResourceType.F_CAPABILITIES, forceRefresh, + capabilityMap==null?null:capabilityMap.get(null), + modifications, result); + + for (ConnectorInstanceSpecificationType additionalConnectorType: resource.asObjectable().getAdditionalConnector()) { + ConnectorSpec connectorSpec = getConnectorSpec(resource, additionalConnectorType); + CapabilitiesType connectorCapType = additionalConnectorType.getCapabilities(); + if (connectorCapType == null) { + connectorCapType = new CapabilitiesType(); + additionalConnectorType.setCapabilities(connectorCapType); + } + ItemPath itemPath = additionalConnectorType.asPrismContainerValue().getPath().append(ConnectorInstanceSpecificationType.F_CAPABILITIES); + completeConnectorCapabilities(connectorSpec, connectorCapType, itemPath, forceRefresh, + capabilityMap==null?null:capabilityMap.get(additionalConnectorType.getName()), + modifications, result); + } + } + + private void completeConnectorCapabilities(ConnectorSpec connectorSpec, CapabilitiesType capType, ItemPath itemPath, boolean forceRefresh, + Collection retrievedCapabilities, Collection> modifications, OperationResult result) + throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { + + if (capType.getNative() != null && !capType.getNative().getAny().isEmpty()) { + if (!forceRefresh) { + CachingMetadataType cachingMetadata = capType.getCachingMetadata(); + if (cachingMetadata == null) { + cachingMetadata = MiscSchemaUtil.generateCachingMetadata(); + modifications.add( + prismContext.deltaFactory().property().createModificationReplaceProperty( + ItemPath.create(ResourceType.F_CAPABILITIES, CapabilitiesType.F_CACHING_METADATA), + connectorSpec.getResource().getDefinition(), + cachingMetadata) + ); + } + return; + } + } + + if (retrievedCapabilities == null) { + try { + + InternalMonitor.recordCount(InternalCounters.CONNECTOR_CAPABILITIES_FETCH_COUNT); + + ConnectorInstance connector = connectorManager.getConfiguredConnectorInstance(connectorSpec, false, result); + retrievedCapabilities = connector.fetchCapabilities(result); + + } catch (GenericFrameworkException e) { + throw new GenericConnectorException("Generic error in connector " + connectorSpec + ": " + + e.getMessage(), e); + } + } + + CapabilityCollectionType nativeCapType = new CapabilityCollectionType(); + capType.setNative(nativeCapType); + nativeCapType.getAny().addAll(retrievedCapabilities); + + CachingMetadataType cachingMetadata = MiscSchemaUtil.generateCachingMetadata(); + capType.setCachingMetadata(cachingMetadata); + + //noinspection unchecked + ObjectDelta capabilitiesReplaceDelta = prismContext.deltaFactory().object() + .createModificationReplaceContainer(ResourceType.class, connectorSpec.getResource().getOid(), + itemPath, capType.asPrismContainerValue().clone()); + + modifications.addAll(capabilitiesReplaceDelta.getModifications()); + } + + private ContainerDelta createSchemaUpdateDelta(PrismObject resource, ResourceSchema resourceSchema) throws SchemaException { + Document xsdDoc; + try { + xsdDoc = resourceSchema.serializeToXsd(); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Serialized XSD resource schema for {}:\n{}", resource, DOMUtil.serializeDOMToString(xsdDoc)); + } + } catch (SchemaException e) { + throw new SchemaException("Error processing resource schema for " + resource + ": " + e.getMessage(), e); + } + + Element xsdElement = DOMUtil.getFirstChildElement(xsdDoc); + if (xsdElement == null) { + throw new SchemaException("No schema was generated for " + resource); + } + CachingMetadataType cachingMetadata = MiscSchemaUtil.generateCachingMetadata(); + + ContainerDelta schemaContainerDelta = prismContext.deltaFactory().container().createDelta( + ResourceType.F_SCHEMA, ResourceType.class); + PrismContainerValue cval = prismContext.itemFactory().createContainerValue(); + schemaContainerDelta.setValueToReplace(cval); + PrismProperty cachingMetadataProperty = cval + .createProperty(XmlSchemaType.F_CACHING_METADATA); + cachingMetadataProperty.setRealValue(cachingMetadata); + List objectClasses = ResourceTypeUtil.getSchemaGenerationConstraints(resource); + if (objectClasses != null) { + PrismProperty generationConstraints = cval + .createProperty(XmlSchemaType.F_GENERATION_CONSTRAINTS); + SchemaGenerationConstraintsType constraints = new SchemaGenerationConstraintsType(); + constraints.getGenerateObjectClass().addAll(objectClasses); + generationConstraints.setRealValue(constraints); + } + PrismProperty definitionProperty = cval.createProperty(XmlSchemaType.F_DEFINITION); + ObjectTypeUtil.setXsdSchemaDefinition(definitionProperty, xsdElement); + + return schemaContainerDelta; + } + + /** + * Apply proper definition (connector schema) to the resource. + */ + private void applyConnectorSchemasToResource(PrismObject resource, Task task, OperationResult result) + throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException { + checkMutable(resource); + PrismObjectDefinition newResourceDefinition = resource.getDefinition().clone(); + for (ConnectorSpec connectorSpec : getAllConnectorSpecs(resource)) { + try { + applyConnectorSchemaToResource(connectorSpec, newResourceDefinition, resource, task, result); + } catch (CommunicationException | ConfigurationException | SecurityViolationException e) { + throw new IllegalStateException("Unexpected exception: " + e.getMessage(), e); // fixme temporary solution + } + } + resource.setDefinition(newResourceDefinition); + } + + /** + * Apply proper definition (connector schema) to the resource. + */ + private void applyConnectorSchemaToResource(ConnectorSpec connectorSpec, PrismObjectDefinition resourceDefinition, + PrismObject resource, Task task, OperationResult result) + throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException { + + ConnectorType connectorType = connectorManager.getConnector(connectorSpec, result); + PrismSchema connectorSchema = connectorManager.getAttachedConnectorSchema(connectorType); + PrismContainerDefinition configurationContainerDefinition = ConnectorTypeUtil + .findConfigurationContainerDefinition(connectorType, connectorSchema); + if (configurationContainerDefinition == null) { + throw new SchemaException("No configuration container definition in schema of " + connectorType); + } + + configurationContainerDefinition = configurationContainerDefinition.clone(); + PrismContainer configurationContainer = connectorSpec.getConnectorConfiguration(); + // We want element name, minOccurs/maxOccurs and similar definition to be taken from the original, not the schema + // the element is global in the connector schema. therefore it does not have correct maxOccurs + if (configurationContainer != null) { + configurationContainerDefinition.adoptElementDefinitionFrom(configurationContainer.getDefinition()); + configurationContainer.applyDefinition(configurationContainerDefinition, true); + + try { + //noinspection unchecked + configurationContainer.accept(visitable -> { + if ((visitable instanceof PrismProperty)) { + try { + evaluateExpression((PrismProperty)visitable, resource, task, result); + } catch (SchemaException | ObjectNotFoundException | ExpressionEvaluationException | CommunicationException | ConfigurationException | SecurityViolationException e) { + throw new TunnelException(e); + } + } + // TODO treat configuration items that are containers themselves + }); + } catch (TunnelException te) { + Throwable e = te.getCause(); + if (e instanceof SchemaException) { + throw (SchemaException)e; + } else if (e instanceof ObjectNotFoundException) { + throw (ObjectNotFoundException)e; + } else if (e instanceof ExpressionEvaluationException) { + throw (ExpressionEvaluationException)e; + } else if (e instanceof CommunicationException) { + throw (CommunicationException)e; + } else if (e instanceof ConfigurationException) { + throw (ConfigurationException)e; + } else if (e instanceof SecurityViolationException) { + throw (SecurityViolationException)e; + } else if (e instanceof RuntimeException) { + throw (RuntimeException)e; + } else if (e instanceof Error) { + throw (Error)e; + } else { + throw new SystemException(e); + } + } + + } else { + configurationContainerDefinition.adoptElementDefinitionFrom( + resourceDefinition.findContainerDefinition(ResourceType.F_CONNECTOR_CONFIGURATION)); + } + + if (connectorSpec.getConnectorName() == null) { + // Default connector, for compatibility + // It does not make sense to update this for any other connectors. + // We cannot have one definition for additionalConnector[1]/connectorConfiguration and + // different definition for additionalConnector[2]/connectorConfiguration in the object definition. + // The way to go is to set up definitions on the container level. + resourceDefinition.replaceDefinition(ResourceType.F_CONNECTOR_CONFIGURATION, configurationContainerDefinition); + } + + } + + private void evaluateExpression(PrismProperty configurationProperty, PrismObject resource, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException { + PrismPropertyDefinition propDef = configurationProperty.getDefinition(); + String shortDesc = "connector configuration property "+configurationProperty+" in "+resource; + List> extraValues = new ArrayList<>(); + for (PrismPropertyValue configurationPropertyValue: configurationProperty.getValues()) { + ExpressionWrapper expressionWrapper = configurationPropertyValue.getExpression(); + if (expressionWrapper == null) { + return; + } + Object expressionObject = expressionWrapper.getExpression(); + if (!(expressionObject instanceof ExpressionType)) { + throw new IllegalStateException("Expected that expression in "+configurationPropertyValue+" will be ExpressionType, but it was "+expressionObject); + } + ExpressionType expressionType = (ExpressionType) expressionWrapper.getExpression(); + + Expression, PrismPropertyDefinition> expression = expressionFactory.makeExpression(expressionType, propDef, MiscSchemaUtil.getExpressionProfile(), shortDesc, task, result); + ExpressionVariables variables = new ExpressionVariables(); + + // TODO: populate variables + + ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContext(null, variables, shortDesc, task); + PrismValueDeltaSetTriple> expressionOutputTriple = expression.evaluate(expressionContext, + result); + Collection> expressionOutputValues = expressionOutputTriple.getNonNegativeValues(); + if (!expressionOutputValues.isEmpty()) { + Iterator> iterator = expressionOutputValues.iterator(); + PrismPropertyValue firstValue = iterator.next(); + configurationPropertyValue.setValue(firstValue.getValue()); + while (iterator.hasNext()) { + extraValues.add(iterator.next()); + } + } + } + for (PrismPropertyValue extraValue: extraValues) { + configurationProperty.add(extraValue); + } + } + + private ResourceSchema fetchResourceSchema(PrismObject resource, Map> capabilityMap, OperationResult parentResult) + throws CommunicationException, GenericFrameworkException, ConfigurationException, ObjectNotFoundException, SchemaException { + ConnectorSpec connectorSpec = selectConnectorSpec(resource, capabilityMap, SchemaCapabilityType.class); + if (connectorSpec == null) { + LOGGER.debug("No connector has schema capability, cannot fetch resource schema"); + return null; + } + InternalMonitor.recordCount(InternalCounters.RESOURCE_SCHEMA_FETCH_COUNT); + List generateObjectClasses = ResourceTypeUtil.getSchemaGenerationConstraints(resource); + ConnectorInstance connectorInstance = connectorManager.getConfiguredConnectorInstance(connectorSpec, false, parentResult); + + LOGGER.debug("Trying to get schema from {}, objectClasses to generate: {}", connectorSpec, generateObjectClasses); + ResourceSchema resourceSchema = connectorInstance.fetchResourceSchema(parentResult); + + if (ResourceTypeUtil.isValidateSchema(resource.asObjectable())) { + ResourceTypeUtil.validateSchema(resourceSchema, resource); + } + return resourceSchema; + + } + + /** + * Test the connection. + * + * @param resource Resource object as fetched from the repository. Must NOT be immutable! + * + * @throws ObjectNotFoundException If the resource object cannot be found in repository (e.g. when trying to set its + * availability status). + */ + public void testConnection(PrismObject resource, Task task, OperationResult parentResult) + throws ObjectNotFoundException { + + checkMutable(resource); + + String resourceOid = resource.getOid(); + + String operationDesc = "test resource " + resourceOid + "connection"; + + List allConnectorSpecs; + try { + allConnectorSpecs = getAllConnectorSpecs(resource); + } catch (SchemaException e) { + String statusChangeReason = operationDesc + ", getting all connectors failed: " + e.getMessage(); + if (LOGGER.isTraceEnabled()) { + LOGGER.error("Configuration error: {}", e.getMessage(), e); + } + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); + parentResult.recordFatalError("Configuration error: " + e.getMessage(), e); + return; + } + + Map> capabilityMap = new HashMap<>(); + for (ConnectorSpec connectorSpec: allConnectorSpecs) { + + OperationResult connectorTestResult = parentResult + .createSubresult(ConnectorTestOperation.CONNECTOR_TEST.getOperation()); + connectorTestResult.addParam(OperationResult.PARAM_NAME, connectorSpec.getConnectorName()); + connectorTestResult.addParam(OperationResult.PARAM_OID, connectorSpec.getConnectorOid()); + + testConnectionConnector(connectorSpec, capabilityMap, task, connectorTestResult); + + connectorTestResult.computeStatus(); + + if (!connectorTestResult.isAcceptable()) { + //nothing more to do.. if it failed while testing connection, status is set. + // we do not need to continue and waste the time. + return; + } + } + + // === test SCHEMA === + + OperationResult schemaResult = parentResult.createSubresult(ConnectorTestOperation.RESOURCE_SCHEMA.getOperation()); + + ResourceSchema schema; + try { + + schema = fetchResourceSchema(resource, capabilityMap, schemaResult); + + } catch (CommunicationException e) { + String statusChangeReason = operationDesc + " failed while fetching schema: " + e.getMessage(); + if (LOGGER.isTraceEnabled()) { + LOGGER.error("Communication error: {}", e.getMessage(), e); + } + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.DOWN, statusChangeReason, task, parentResult, true); + schemaResult.recordFatalError("Communication error: " + e.getMessage(), e); + return; + } catch (GenericFrameworkException | ConfigurationException | ObjectNotFoundException | SchemaException | RuntimeException e) { + String statusChangeReason = operationDesc + " failed while fetching schema: " + e.getMessage(); + if (LOGGER.isTraceEnabled()) { + LOGGER.error("Error: {}", e.getMessage(), e); + } + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); + schemaResult.recordFatalError("Error: " + e.getMessage(), e); + return; + } + + if (schema == null || schema.isEmpty()) { + // Resource does not support schema + // If there is a static schema in resource definition this may still be OK + try { + schema = RefinedResourceSchemaImpl.getResourceSchema(resource, prismContext); + } catch (SchemaException e) { + String statusChangeReason = operationDesc + " failed while parsing refined schema: " + e.getMessage(); + if (LOGGER.isTraceEnabled()) { + LOGGER.error("Error: {}", e.getMessage(), e); + } + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); + schemaResult.recordFatalError(e); + return; + } + + if (schema == null || schema.isEmpty()) { + String msg = "Connector does not support schema and no static schema available"; + String statusChangeReason = operationDesc + ". " + msg; + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); + schemaResult.recordFatalError(msg); + return; + } + } + + // Invoke completeResource(). This will store the fetched schema to the ResourceType if there is no + // definition already. Therefore the testResource() can be used to generate the resource schema - until we + // have full schema caching capability. + PrismObject completedResource; + try { + // Re-fetching from repository to get up-to-date availability status (to avoid phantom state change records). + PrismObject repoResource = repositoryService.getObject(ResourceType.class, resourceOid, null, schemaResult); + completedResource = completeResourceInternal(repoResource, schema, true, capabilityMap, null, task, schemaResult); + } catch (ObjectNotFoundException e) { + String msg = "Object not found (unexpected error, probably a bug): " + e.getMessage(); + String statusChangeReason = operationDesc + " failed while completing resource. " + msg; + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); + schemaResult.recordFatalError(msg, e); + return; + } catch (SchemaException e) { + String msg = "Schema processing error (probably connector bug): " + e.getMessage(); + String statusChangeReason = operationDesc + " failed while completing resource. " + msg; + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); + schemaResult.recordFatalError(msg, e); + return; + } catch (ExpressionEvaluationException e) { + String msg = "Expression error: " + e.getMessage(); + String statusChangeReason = operationDesc + " failed while completing resource. " + msg; + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); + schemaResult.recordFatalError(msg, e); + return; + } catch (RuntimeException e) { + String msg = "Unspecified exception: " + e.getMessage(); + String statusChangeReason = operationDesc + " failed while completing resource. " + msg; + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); + schemaResult.recordFatalError(msg, e); + return; + } + + schemaResult.recordSuccess(); + + try { + updateResourceSchema(allConnectorSpecs, parentResult, completedResource); + } catch (SchemaException | ObjectNotFoundException | CommunicationException | ConfigurationException | RuntimeException e) { + String statusChangeReason = operationDesc + " failed while updating resource schema: " + e.getMessage(); + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, statusChangeReason, task, parentResult, true); + parentResult.recordFatalError("Couldn't update resource schema: " + e.getMessage(), e); + //noinspection UnnecessaryReturnStatement + return; + } + + // TODO: connector sanity (e.g. refined schema, at least one account type, identifiers + // in schema, etc.) + + } + + private void checkMutable(PrismObject resource) { + if (resource.isImmutable()) { + throw new IllegalArgumentException("Got immutable resource object, while expecting mutable one: " + resource); + } + } + + private void updateResourceSchema(List allConnectorSpecs, OperationResult parentResult, + PrismObject resource) + throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException { + ResourceSchema resourceSchema = RefinedResourceSchemaImpl.getResourceSchema(resource, prismContext); + if (resourceSchema != null) { + for (ConnectorSpec connectorSpec : allConnectorSpecs) { + ConnectorInstance instance = connectorManager.getConfiguredConnectorInstance(connectorSpec, false, parentResult); + instance.updateSchema(resourceSchema); + } + } + } + + private void testConnectionConnector(ConnectorSpec connectorSpec, Map> capabilityMap, Task task, + OperationResult parentResult) throws ObjectNotFoundException { + + // === test INITIALIZATION === + + OperationResult initResult = parentResult + .createSubresult(ConnectorTestOperation.CONNECTOR_INITIALIZATION.getOperation()); + + LOGGER.debug("Testing connection using {}", connectorSpec); + String resourceOid = connectorSpec.getResource().getOid(); + + String operationCtx = "testing connection using " + connectorSpec; + + ConfiguredConnectorInstanceEntry connectorInstanceCacheEntry; + try { + // Make sure we are getting non-configured instance. + connectorInstanceCacheEntry = connectorManager.getConnectorInstanceCacheEntry(connectorSpec, initResult); + initResult.recordSuccess(); + } catch (ObjectNotFoundException e) { + // The connector was not found. The resource definition is either + // wrong or the connector is not installed. + String msg = "The connector was not found: "+e.getMessage(); + operationCtx += " failed while getting connector instance. " + msg; + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); + initResult.recordFatalError(msg, e); + return; + } catch (SchemaException e) { + String msg = "Schema error while dealing with the connector definition: "+e.getMessage(); + operationCtx += " failed while getting connector instance. " + msg; + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); + initResult.recordFatalError(msg, e); + return; + } catch (RuntimeException | Error e) { + String msg = "Unexpected runtime error: "+e.getMessage(); + operationCtx += " failed while getting connector instance. " + msg; + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); + initResult.recordFatalError(msg, e); + return; + } catch (CommunicationException e) { + String msg = "Communication error: "+e.getMessage(); + operationCtx += " failed while getting connector instance. " + msg; + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.DOWN, operationCtx, task, parentResult, true); + initResult.recordFatalError(msg, e); + return; + } catch (ConfigurationException e) { + String msg = "Configuration error: "+e.getMessage(); + operationCtx += " failed while getting connector instance. " + msg; + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); + initResult.recordFatalError(msg, e); + return; + } + + ConnectorInstance connector = connectorInstanceCacheEntry.getConnectorInstance(); + + + // === test CONFIGURATION === + + OperationResult configResult = parentResult + .createSubresult(ConnectorTestOperation.CONNECTOR_CONFIGURATION.getOperation()); + + try { + PrismObject resource = connectorSpec.getResource(); + PrismObjectDefinition newResourceDefinition = resource.getDefinition().clone(); + applyConnectorSchemaToResource(connectorSpec, newResourceDefinition, resource, task, configResult); + PrismContainerValue connectorConfiguration = connectorSpec.getConnectorConfiguration().getValue(); + + InternalMonitor.recordCount(InternalCounters.CONNECTOR_INSTANCE_CONFIGURATION_COUNT); + + connector.configure(connectorConfiguration, ResourceTypeUtil.getSchemaGenerationConstraints(resource), configResult); + + // We need to explicitly initialize the instance, e.g. in case that the schema and capabilities + // cannot be detected by the connector and therefore are provided in the resource + // + // NOTE: the capabilities and schema that are used here are NOT necessarily those that are detected by the resource. + // The detected schema will come later. The schema here is the one that is stored in the resource + // definition (ResourceType). This may be schema that was detected previously. But it may also be a schema + // that was manually defined. This is needed to be passed to the connector in case that the connector + // cannot detect the schema and needs schema/capabilities definition to establish a connection. + // Most connectors will just ignore the schema and capabilities that are provided here. + // But some connectors may need it (e.g. CSV connector working with CSV file without a header). + // + ResourceSchema previousResourceSchema = RefinedResourceSchemaImpl.getResourceSchema(connectorSpec.getResource(), prismContext); + Collection previousCapabilities = ResourceTypeUtil.getNativeCapabilitiesCollection(connectorSpec.getResource().asObjectable()); + connector.initialize(previousResourceSchema, previousCapabilities, + ResourceTypeUtil.isCaseIgnoreAttributeNames(connectorSpec.getResource().asObjectable()), configResult); + + configResult.recordSuccess(); + } catch (CommunicationException e) { + operationCtx += " failed while testing configuration: " + e.getMessage(); + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.DOWN, operationCtx, task, parentResult, true); + configResult.recordFatalError("Communication error", e); + return; + } catch (GenericFrameworkException e) { + operationCtx += " failed while testing configuration: " + e.getMessage(); + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); + configResult.recordFatalError("Generic error", e); + return; + } catch (SchemaException e) { + operationCtx += " failed while testing configuration: " + e.getMessage(); + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); + configResult.recordFatalError("Schema error", e); + return; + } catch (ConfigurationException e) { + operationCtx += " failed while testing configuration: " + e.getMessage(); + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); + configResult.recordFatalError("Configuration error", e); + return; + } catch (ObjectNotFoundException e) { + operationCtx += " failed while testing configuration: " + e.getMessage(); + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); + configResult.recordFatalError("Object not found", e); + return; + } catch (ExpressionEvaluationException e) { + operationCtx += " failed while testing configuration: " + e.getMessage(); + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); + configResult.recordFatalError("Expression error", e); + return; + } catch (SecurityViolationException e) { + operationCtx += " failed while testing configuration: " + e.getMessage(); + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); + configResult.recordFatalError("Security violation", e); + return; + } catch (RuntimeException | Error e) { + operationCtx += " failed while testing configuration: " + e.getMessage(); + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); + configResult.recordFatalError("Unexpected runtime error", e); + return; + } + + // === test CONNECTION === + + // delegate the main part of the test to the connector + connector.test(parentResult); + + parentResult.computeStatus(); + if (!parentResult.isAcceptable()) { + operationCtx += ". Connector test failed: " + parentResult.getMessage(); + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.DOWN, operationCtx, task, parentResult, true); + // No point in going on. Following tests will fail anyway, they will + // just produce misleading + // messages. + return; + } else { + operationCtx += ". Connector test successful."; + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.UP, operationCtx, task, parentResult, false); + } + + // === test CAPABILITIES === + + OperationResult capabilitiesResult = parentResult + .createSubresult(ConnectorTestOperation.CONNECTOR_CAPABILITIES.getOperation()); + try { + InternalMonitor.recordCount(InternalCounters.CONNECTOR_CAPABILITIES_FETCH_COUNT); + Collection retrievedCapabilities = connector.fetchCapabilities(capabilitiesResult); + + capabilityMap.put(connectorSpec.getConnectorName(), retrievedCapabilities); + capabilitiesResult.recordSuccess(); + } catch (CommunicationException e) { + operationCtx += " failed while testing capabilities: " + e.getMessage(); + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.DOWN, operationCtx, task, parentResult, true); + capabilitiesResult.recordFatalError("Communication error", e); + return; + } catch (GenericFrameworkException e) { + operationCtx += " failed while testing capabilities: " + e.getMessage(); + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); + capabilitiesResult.recordFatalError("Generic error", e); + return; + } catch (ConfigurationException e) { + operationCtx += " failed while testing capabilities: " + e.getMessage(); + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); + capabilitiesResult.recordFatalError("Configuration error", e); + return; + } catch (SchemaException e) { + operationCtx += " failed while testing capabilities: " + e.getMessage(); + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); + capabilitiesResult.recordFatalError("Schema error", e); + return; + } catch (RuntimeException | Error e) { + operationCtx += " failed while testing capabilities: " + e.getMessage(); + modifyResourceAvailabilityStatus(resourceOid, AvailabilityStatusType.BROKEN, operationCtx, task, parentResult, true); + capabilitiesResult.recordFatalError("Unexpected runtime error", e); + return; + } + + // Connector instance is fully configured at this point. + // But the connector cache entry may not be set up properly and it is not yet placed into the cache. + // Therefore make sure the caching bit is completed. + // Place the connector to cache even if it was configured at the beginning. The connector is reconfigured now. + connectorManager.cacheConfiguredConnector(connectorInstanceCacheEntry, connectorSpec); + } + + /** + * Modifies resource availability status in the repository (if needed). + * + * The necessity of status modification is determined against the current version of the resource - unless "skipGetResource" + * is set. The resource is hopefully cached ResourceCache, so the performance impact should be almost ponone. + * + * Also note that in-memory representation of the resource is not modified. As a side effect, the cached resource + * is invalidated because of the modification. But it will be loaded on the next occasion. This should be quite harmless, + * as we do not expect availability changes to occur frequently. + * + * @param statusChangeReason Description of the reason of changing the availability status. + * @param skipGetResource True if we want to skip "getResource" operation and therefore apply the change regardless of + * the current resource availability status. This is to be used in situations where we expect that + * the resource might not be successfully retrievable (e.g. if it's broken). + * + * @throws ObjectNotFoundException If the resource object does not exist in repository. + */ + public void modifyResourceAvailabilityStatus(String resourceOid, AvailabilityStatusType newStatus, String statusChangeReason, + Task task, OperationResult result, boolean skipGetResource) throws ObjectNotFoundException { + + AvailabilityStatusType currentStatus; + String resourceDesc; + PrismObject resource; + if (skipGetResource) { + resource = null; + currentStatus = null; + resourceDesc = "resource " + resourceOid; + } else { + try { + resource = getResource(resourceOid, GetOperationOptions.createNoFetch(), task, result); + } catch (SchemaException | ExpressionEvaluationException e) { + // We actually do not expect any of these exceptions here. The resource is most probably in use + result.recordFatalError("Unexpected exception: " + e.getMessage(), e); + throw new SystemException("Unexpected exception: " + e.getMessage(), e); + } + ResourceType resourceBean = resource.asObjectable(); + currentStatus = ResourceTypeUtil.getLastAvailabilityStatus(resourceBean); + resourceDesc = resource.toString(); + } + + if (newStatus != currentStatus) { + try { + List> modifications = operationalStateManager.createAndLogOperationalStateDeltas(currentStatus, newStatus, + resourceDesc, statusChangeReason, resource); + repositoryService.modifyObject(ResourceType.class, resourceOid, modifications, result); + result.computeStatusIfUnknown(); + InternalMonitor.recordCount(InternalCounters.RESOURCE_REPOSITORY_MODIFY_COUNT); + } catch (SchemaException | ObjectAlreadyExistsException e) { + throw new SystemException("Unexpected exception while recording operation state change: " + e.getMessage(), e); + } + } + } + + /** + * Adjust scheme with respect to capabilities. E.g. disable attributes that + * are used for special purpose (such as account activation simulation). + * + * TODO treat also objectclass-specific capabilities here + */ + private void adjustSchemaForSimulatedCapabilities(PrismObject resource, ResourceSchema resourceSchema) { + ResourceType resourceType = resource.asObjectable(); + if (resourceType.getCapabilities() == null || resourceType.getCapabilities().getConfigured() == null) { + return; + } + ActivationCapabilityType activationCapability = CapabilityUtil.getCapability(resourceType + .getCapabilities().getConfigured().getAny(), ActivationCapabilityType.class); + if (CapabilityUtil.getEffectiveActivationStatus(activationCapability) != null) { + QName attributeName = activationCapability.getStatus().getAttribute(); + Boolean ignore = activationCapability.getStatus().isIgnoreAttribute(); + if (attributeName != null) { + // The attribute used for enable/disable simulation should be ignored in the schema + // otherwise strange things may happen, such as changing the same attribute both from + // activation/enable and from the attribute using its native name. + for (ObjectClassComplexTypeDefinition objectClassDefinition : resourceSchema + .getDefinitions(ObjectClassComplexTypeDefinition.class)) { + ResourceAttributeDefinition attributeDefinition = objectClassDefinition + .findAttributeDefinition(attributeName); + if (attributeDefinition != null) { + if (ignore == null || ignore) { + ((MutableItemDefinition) attributeDefinition).setProcessing(ItemProcessing.IGNORE); + } + } else { + // simulated activation attribute points to something that is not in the schema + // technically, this is an error. But it looks to be quite common in connectors. + // The enable/disable is using operational attributes that are not exposed in the + // schema, but they work if passed to the connector. + // Therefore we don't want to break anything. We could log an warning here, but the + // warning would be quite frequent. Maybe a better place to warn user would be import + // of the object. + LOGGER.debug("Simulated activation attribute " + + attributeName + + " for objectclass " + + objectClassDefinition.getTypeName() + + " in " + + resource + + " does not exist in the resource schema. This may work well, but it is not clean. Connector exposing such schema should be fixed."); + } + } + } + } + } + + public void applyDefinition(ObjectDelta delta, ResourceType resourceWhenNoOid, GetOperationOptions options, Task task, OperationResult objectResult) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException { + + if (delta.isAdd()) { + PrismObject resource = delta.getObjectToAdd(); + applyConnectorSchemasToResource(resource, task, objectResult); + return; + + } else if (delta.isModify()) { + // Go on + } else { + return; + } + + if (delta.hasCompleteDefinition()){ + //nothing to do, all modifications has definitions..just aplly this deltas.. + return; + } + + + PrismObject resource; + String resourceOid = delta.getOid(); + if (resourceOid == null) { + Validate.notNull(resourceWhenNoOid, "Resource oid not specified in the object delta, and resource is not specified as well. Could not apply definition."); + resource = resourceWhenNoOid.asPrismObject(); + } else { + resource = getResource(resourceOid, options, task, objectResult); + } + + ResourceType resourceType = resource.asObjectable(); +// ResourceType resourceType = completeResource(resource.asObjectable(), null, objectResult); + //TODO TODO TODO FIXME FIXME FIXME copied from ObjectImprted..union this two cases + PrismContainer configurationContainer = ResourceTypeUtil.getConfigurationContainer(resourceType); + if (configurationContainer == null || configurationContainer.isEmpty()) { + // Nothing to check + objectResult.recordWarning("The resource has no configuration"); + return; + } + + // Check the resource configuration. The schema is in connector, so fetch the connector first + String connectorOid = resourceType.getConnectorRef().getOid(); + if (StringUtils.isBlank(connectorOid)) { + objectResult.recordFatalError("The connector reference (connectorRef) is null or empty"); + return; + } + + //ItemDelta.findItemDelta(delta.getModifications(), ResourceType.F_SCHEMA, ContainerDelta.class) == null || + + ReferenceDelta connectorRefDelta = ItemDeltaCollectionsUtil.findReferenceModification(delta.getModifications(), ResourceType.F_CONNECTOR_REF); + if (connectorRefDelta != null){ + Item connectorRefNew = connectorRefDelta.getItemNewMatchingPath(null); + if (connectorRefNew.getValues().size() == 1){ + PrismReferenceValue connectorRefValue = connectorRefNew.getValues().iterator().next(); + if (connectorRefValue.getOid() != null && !connectorOid.equals(connectorRefValue.getOid())){ + connectorOid = connectorRefValue.getOid(); + } + } + } + + PrismObject connector; + ConnectorType connectorType; + try { + connector = repositoryService.getObject(ConnectorType.class, connectorOid, null, objectResult); + connectorType = connector.asObjectable(); + } catch (ObjectNotFoundException e) { + // No connector, no fun. We can't check the schema. But this is referential integrity problem. + // Mark the error ... there is nothing more to do + objectResult.recordFatalError("Connector (OID:" + connectorOid + ") referenced from the resource is not in the repository", e); + return; + } catch (SchemaException e) { + // Probably a malformed connector. To be kind of robust, lets allow the import. + // Mark the error ... there is nothing more to do + objectResult.recordPartialError("Connector (OID:" + connectorOid + ") referenced from the resource has schema problems: " + e.getMessage(), e); + LOGGER.error("Connector (OID:{}) referenced from the imported resource \"{}\" has schema problems: {}-{}", + connectorOid, resourceType.getName(), e.getMessage(), e); + return; + } + + Element connectorSchemaElement = ConnectorTypeUtil.getConnectorXsdSchema(connector); + MutablePrismSchema connectorSchema; + if (connectorSchemaElement == null) { + // No schema to validate with + return; + } + try { + connectorSchema = prismContext.schemaFactory().createPrismSchema(DOMUtil.getSchemaTargetNamespace(connectorSchemaElement)); + connectorSchema.parseThis(connectorSchemaElement, true, "schema for " + connector, prismContext); + } catch (SchemaException e) { + objectResult.recordFatalError("Error parsing connector schema for " + connector + ": "+e.getMessage(), e); + return; + } + QName configContainerQName = new QName(connectorType.getNamespace(), ResourceType.F_CONNECTOR_CONFIGURATION.getLocalPart()); + PrismContainerDefinition configContainerDef = + connectorSchema.findContainerDefinitionByElementName(configContainerQName); + if (configContainerDef == null) { + objectResult.recordFatalError("Definition of configuration container " + configContainerQName + " not found in the schema of of " + connector); + return; + } + + try { + configurationContainer.applyDefinition(configContainerDef); + } catch (SchemaException e) { + objectResult.recordFatalError("Configuration error in " + resource + ": "+e.getMessage(), e); + return; + } + + PrismContainer configContainer = resourceType.asPrismObject().findContainer(ResourceType.F_CONNECTOR_CONFIGURATION); + //noinspection unchecked + configContainer.applyDefinition(configContainerDef); + + for (ItemDelta itemDelta : delta.getModifications()){ + applyItemDefinition(itemDelta, configContainerDef, objectResult); + } + } + + private void applyItemDefinition(ItemDelta itemDelta, + PrismContainerDefinition configContainerDef, OperationResult objectResult) throws SchemaException { + if (itemDelta.getParentPath() == null){ + LOGGER.trace("No parent path defined for item delta {}", itemDelta); + return; + } + + QName first = itemDelta.getParentPath().firstToNameOrNull(); + if (first == null) { + return; + } + + if (itemDelta.getDefinition() == null && (ResourceType.F_CONNECTOR_CONFIGURATION.equals(first) || ResourceType.F_SCHEMA.equals(first))){ + ItemPath path = itemDelta.getPath().rest(); + D itemDef = configContainerDef.findItemDefinition(path); + if (itemDef == null){ + LOGGER.warn("No definition found for item {}. Check your namespaces?", path); + objectResult.recordWarning("No definition found for item delta: " + itemDelta +". Check your namespaces?" ); +// throw new SchemaException("No definition found for item " + path+ ". Check your namespaces?" ); + return; + } + itemDelta.applyDefinition(itemDef); + + } + } + + public void applyDefinition(PrismObject resource, Task task, OperationResult parentResult) + throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException { + applyConnectorSchemasToResource(resource, task, parentResult); + } + + @SuppressWarnings("unused") + public void applyDefinition(ObjectQuery query, OperationResult result) { + // TODO: not implemented yet + } + + public Object executeScript(String resourceOid, ProvisioningScriptType script, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException { + PrismObject resource = getResource(resourceOid, null, task, result); + ConnectorSpec connectorSpec = selectConnectorSpec(resource, ScriptCapabilityType.class); + if (connectorSpec == null) { + throw new UnsupportedOperationException("No connector supports script capability"); + } + ConnectorInstance connectorInstance = connectorManager.getConfiguredConnectorInstance(connectorSpec, false, result); + ExecuteProvisioningScriptOperation scriptOperation = ProvisioningUtil.convertToScriptOperation(script, "script on "+resource, prismContext); + try { + StateReporter reporter = new StateReporter(resourceOid, task); + return connectorInstance.executeScript(scriptOperation, reporter, result); + } catch (GenericFrameworkException e) { + // Not expected. Transform to system exception + result.recordFatalError("Generic provisioning framework error", e); + throw new SystemException("Generic provisioning framework error: " + e.getMessage(), e); + } + } + + public List getConnectorOperationalStatus(PrismObject resource, OperationResult result) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException { + List statuses = new ArrayList<>(); + for (ConnectorSpec connectorSpec: getAllConnectorSpecs(resource)) { + ConnectorInstance connectorInstance = connectorManager.getConfiguredConnectorInstance(connectorSpec, false, result); + ConnectorOperationalStatus operationalStatus = connectorInstance.getOperationalStatus(); + if (operationalStatus != null) { + operationalStatus.setConnectorName(connectorSpec.getConnectorName()); + statuses.add(operationalStatus); + } + } + return statuses; + } + + private List getAllConnectorSpecs(PrismObject resource) throws SchemaException { + List connectorSpecs = new ArrayList<>(); + connectorSpecs.add(getDefaultConnectorSpec(resource)); + for (ConnectorInstanceSpecificationType additionalConnectorType: resource.asObjectable().getAdditionalConnector()) { + connectorSpecs.add(getConnectorSpec(resource, additionalConnectorType)); + } + return connectorSpecs; + } + + // Should be used only internally (private). But it is public, because it is accessed from the tests. + public ConnectorInstance getConfiguredConnectorInstance(PrismObject resource, + Class operationCapabilityClass, boolean forceFresh, OperationResult parentResult) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException { + ConnectorSpec connectorSpec = selectConnectorSpec(resource, operationCapabilityClass); + if (connectorSpec == null) { + return null; + } + return connectorManager.getConfiguredConnectorInstance(connectorSpec, forceFresh, parentResult); + } + + // Used by the tests. Does not change anything. + @SuppressWarnings("SameParameterValue") + ConnectorInstance getConfiguredConnectorInstanceFromCache(PrismObject resource, + Class operationCapabilityClass) throws SchemaException { + ConnectorSpec connectorSpec = selectConnectorSpec(resource, operationCapabilityClass); + return connectorSpec != null ? connectorManager.getConfiguredConnectorInstanceFromCache(connectorSpec) : null; + } + + CapabilitiesType getConnectorCapabilities(ResourceType resource, + RefinedObjectClassDefinition objectClassDefinition, Class operationCapabilityClass) { + if (resource == null) { + return null; + } + + CapabilitiesType connectorCapabilities = null; + for (ConnectorInstanceSpecificationType additionalConnectorType : resource.getAdditionalConnector()) { + if (supportsCapability(additionalConnectorType, operationCapabilityClass)) { + connectorCapabilities = additionalConnectorType.getCapabilities(); + } + } + + if (connectorCapabilities == null) { + connectorCapabilities = resource.getCapabilities(); + } + + CapabilitiesType finalCapabilities = applyObjectClassCapabilities(connectorCapabilities, objectClassDefinition); + LOGGER.trace("Returning final capabilities:\n{} ", finalCapabilities); + return finalCapabilities; + + } + + private CapabilitiesType applyObjectClassCapabilities(CapabilitiesType connectorCapabilities, RefinedObjectClassDefinition objectClassDefinition) { + + if (objectClassDefinition == null) { + return connectorCapabilities; + } + + CapabilitiesType objectClassCapabilities = objectClassDefinition.getCapabilities(); + if (objectClassCapabilities == null) { + LOGGER.trace("No capabilities for {} specified, skipping merge.", objectClassDefinition); + return connectorCapabilities; + } + + CapabilityCollectionType configured = objectClassCapabilities.getConfigured(); + if (configured == null) { + LOGGER.trace("Empty capabilities in {} specified, skipping merge", objectClassDefinition); + return connectorCapabilities; + } + + CapabilitiesType finalCapabilities = new CapabilitiesType(); + if (connectorCapabilities.getNative() != null) { + finalCapabilities.setNative(connectorCapabilities.getNative()); + } + + if (!hasConfiguredCapabilities(connectorCapabilities)) { + LOGGER.trace("No configured capabilities found for connector, replacing with capabilities defined for {}", objectClassDefinition); + finalCapabilities.setConfigured(configured); + return finalCapabilities; + } + + for (Object capability : connectorCapabilities.getConfigured().getAny()) { + + if (!CapabilityUtil.containsCapabilityWithSameElementName(configured.getAny(), capability)) { + configured.getAny().add(capability); + } + } + + finalCapabilities.setConfigured(configured); + return finalCapabilities; + } + + private boolean hasConfiguredCapabilities(CapabilitiesType supportedCapabilities) { + CapabilityCollectionType configured = supportedCapabilities.getConfigured(); + return configured != null && !configured.getAny().isEmpty(); + } + + @SuppressWarnings("SameParameterValue") + private ConnectorSpec selectConnectorSpec(PrismObject resource, Map> capabilityMap, Class capabilityClass) throws SchemaException { + if (capabilityMap == null) { + return selectConnectorSpec(resource, capabilityClass); + } + for (ConnectorInstanceSpecificationType additionalConnectorType: resource.asObjectable().getAdditionalConnector()) { + if (supportsCapability(additionalConnectorType, capabilityMap.get(additionalConnectorType.getName()), capabilityClass)) { + return getConnectorSpec(resource, additionalConnectorType); + } + } + return getDefaultConnectorSpec(resource); + } + + private ConnectorSpec selectConnectorSpec(PrismObject resource, Class operationCapabilityClass) throws SchemaException { + for (ConnectorInstanceSpecificationType additionalConnectorType: resource.asObjectable().getAdditionalConnector()) { + if (supportsCapability(additionalConnectorType, operationCapabilityClass)) { + return getConnectorSpec(resource, additionalConnectorType); + } + } + return getDefaultConnectorSpec(resource); + } + + private boolean supportsCapability(ConnectorInstanceSpecificationType additionalConnectorType, Class capabilityClass) { + T cap = CapabilityUtil.getEffectiveCapability(additionalConnectorType.getCapabilities(), capabilityClass); + return CapabilityUtil.isCapabilityEnabled(cap); + } + + private boolean supportsCapability(ConnectorInstanceSpecificationType additionalConnectorType, Collection nativeCapabilities, Class capabilityClass) { + CapabilitiesType specifiedCapabilitiesType = additionalConnectorType.getCapabilities(); + if (specifiedCapabilitiesType != null) { + CapabilityCollectionType configuredCapCollectionType = specifiedCapabilitiesType.getConfigured(); + if (configuredCapCollectionType != null) { + T configuredCap = CapabilityUtil.getCapability(configuredCapCollectionType.getAny(), capabilityClass); + if (configuredCap != null && !CapabilityUtil.isCapabilityEnabled(configuredCap)) { + return false; + } + } + + } + T cap = CapabilityUtil.getCapability(nativeCapabilities, capabilityClass); + return CapabilityUtil.isCapabilityEnabled(cap); + } + + private ConnectorSpec getDefaultConnectorSpec(PrismObject resource) { + PrismContainer connectorConfiguration = resource.findContainer(ResourceType.F_CONNECTOR_CONFIGURATION); + return new ConnectorSpec(resource, null, ResourceTypeUtil.getConnectorOid(resource), connectorConfiguration); + } + + private ConnectorSpec getConnectorSpec(PrismObject resource, ConnectorInstanceSpecificationType additionalConnectorType) throws SchemaException { + if (additionalConnectorType.getConnectorRef() == null) { + throw new SchemaException("No connector reference in additional connector in "+resource); + } + String connectorOid = additionalConnectorType.getConnectorRef().getOid(); + if (StringUtils.isBlank(connectorOid)) { + throw new SchemaException("No connector OID in additional connector in "+resource); + } + //noinspection unchecked + PrismContainer connectorConfiguration = additionalConnectorType.asPrismContainerValue().findContainer(ConnectorInstanceSpecificationType.F_CONNECTOR_CONFIGURATION); + String connectorName = additionalConnectorType.getName(); + if (StringUtils.isBlank(connectorName)) { + throw new SchemaException("No connector name in additional connector in "+resource); + } + return new ConnectorSpec(resource, connectorName, connectorOid, connectorConfiguration); + } + + public PrismContext getPrismContext() { + return prismContext; + } +} diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/sync/ChangeProcessingCoordinator.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/sync/ChangeProcessingCoordinator.java index e08a759aabe..5b915ebabfa 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/sync/ChangeProcessingCoordinator.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/sync/ChangeProcessingCoordinator.java @@ -121,7 +121,7 @@ private void createWorkerTasks(int threadsCount) { } private class WorkerHandler implements LightweightTaskHandler { - private OperationResult workerSpecificResult; + private final OperationResult workerSpecificResult; private WorkerHandler(OperationResult workerSpecificResult) { this.workerSpecificResult = workerSpecificResult; diff --git a/provisioning/ucf-impl-connid/src/main/java/com/evolveum/midpoint/provisioning/ucf/impl/connid/ConnIdCapabilitiesAndSchemaParser.java b/provisioning/ucf-impl-connid/src/main/java/com/evolveum/midpoint/provisioning/ucf/impl/connid/ConnIdCapabilitiesAndSchemaParser.java index 1fe743c1fa5..65e520050e2 100644 --- a/provisioning/ucf-impl-connid/src/main/java/com/evolveum/midpoint/provisioning/ucf/impl/connid/ConnIdCapabilitiesAndSchemaParser.java +++ b/provisioning/ucf-impl-connid/src/main/java/com/evolveum/midpoint/provisioning/ucf/impl/connid/ConnIdCapabilitiesAndSchemaParser.java @@ -247,7 +247,7 @@ private org.identityconnectors.framework.common.objects.Schema fetchConnIdSchema // Connector operation cannot create result for itself, so we need to create result for it OperationResult connIdSchemaResult = parentResult.createSubresult(ConnectorFacade.class.getName() + ".schema"); connIdSchemaResult.addContext("connector", connIdConnectorFacade.getClass()); - org.identityconnectors.framework.common.objects.Schema connIdSchema = null; + org.identityconnectors.framework.common.objects.Schema connIdSchema; try { LOGGER.debug("Fetching schema from {}", connectorHumanReadableName); diff --git a/repo/audit-api/src/main/java/com/evolveum/midpoint/audit/api/AuditEventRecord.java b/repo/audit-api/src/main/java/com/evolveum/midpoint/audit/api/AuditEventRecord.java index 414b6f3d3b2..9a6e20c5e17 100644 --- a/repo/audit-api/src/main/java/com/evolveum/midpoint/audit/api/AuditEventRecord.java +++ b/repo/audit-api/src/main/java/com/evolveum/midpoint/audit/api/AuditEventRecord.java @@ -492,7 +492,7 @@ public void checkConsistence() { // } } - public AuditEventRecordType createAuditEventRecordType(){ + public AuditEventRecordType createAuditEventRecordType() { return createAuditEventRecordType(false); } @@ -522,7 +522,12 @@ public AuditEventRecordType createAuditEventRecordType(boolean tolerateInconsist for (ObjectDeltaOperation delta : deltas) { ObjectDeltaOperationType odo = new ObjectDeltaOperationType(); try { - DeltaConvertor.toObjectDeltaOperationType(delta, odo, DeltaConversionOptions.createSerializeReferenceNames()); + DeltaConversionOptions options = DeltaConversionOptions.createSerializeReferenceNames(); + // This can be tricky because it can create human-readable but machine-unprocessable + // data, see MID-6262. But in current context the results of this method are to be + // used only in GUI and reports, so we are safe here. + options.setEscapeInvalidCharacters(true); + DeltaConvertor.toObjectDeltaOperationType(delta, odo, options); auditRecordType.getDelta().add(odo); } catch (Exception e) { if (tolerateInconsistencies){ diff --git a/repo/audit-api/src/main/java/com/evolveum/midpoint/audit/api/AuditService.java b/repo/audit-api/src/main/java/com/evolveum/midpoint/audit/api/AuditService.java index f61854cdc3d..c4d4e12ab66 100644 --- a/repo/audit-api/src/main/java/com/evolveum/midpoint/audit/api/AuditService.java +++ b/repo/audit-api/src/main/java/com/evolveum/midpoint/audit/api/AuditService.java @@ -12,6 +12,7 @@ import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.xml.ns._public.common.common_3.CleanupPolicyType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationAuditType; /** * @author semancik @@ -54,4 +55,9 @@ public interface AuditService { */ boolean supportsRetrieval(); + /** + * Called when audit configuration is established or changed. + */ + default void applyAuditConfiguration(SystemConfigurationAuditType configuration) { + } } diff --git a/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/global/GlobalObjectCache.java b/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/global/GlobalObjectCache.java index 7b76cd949cf..cd6a76aaa7a 100644 --- a/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/global/GlobalObjectCache.java +++ b/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/global/GlobalObjectCache.java @@ -7,6 +7,7 @@ package com.evolveum.midpoint.repo.cache.global; +import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.schema.cache.CacheType; import com.evolveum.midpoint.util.caching.CacheConfiguration; import com.evolveum.midpoint.util.logging.Trace; @@ -104,7 +105,9 @@ public void remove(@NotNull Class type, String oid) { public void put(GlobalCacheObjectValue cacheObject) { if (cache != null) { - cacheObject.getObject().checkImmutable(); + PrismObject prismObject = cacheObject.getObject(); + prismObject.checkImmutable(); + LOGGER.trace("Putting {} into cache (v{})", prismObject, prismObject.getVersion()); cache.put(cacheObject.getObjectOid(), cacheObject); } } diff --git a/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/handlers/CachingResultHandler.java b/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/handlers/CachingResultHandler.java index ef49e60cf79..0c24e01f509 100644 --- a/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/handlers/CachingResultHandler.java +++ b/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/handlers/CachingResultHandler.java @@ -65,6 +65,7 @@ public boolean handle(PrismObject object, OperationResult parentResult) { } else { CachePerformanceCollector.INSTANCE.registerOverSizedQuery(type); overflown = true; + objects.clear(); } } diff --git a/repo/repo-cache/src/test/java/com/evolveum/midpoint/repo/cache/TestRepositoryCache.java b/repo/repo-cache/src/test/java/com/evolveum/midpoint/repo/cache/TestRepositoryCache.java index 6e5a8a973b7..6e112bc2241 100644 --- a/repo/repo-cache/src/test/java/com/evolveum/midpoint/repo/cache/TestRepositoryCache.java +++ b/repo/repo-cache/src/test/java/com/evolveum/midpoint/repo/cache/TestRepositoryCache.java @@ -12,10 +12,12 @@ import static com.evolveum.midpoint.prism.util.PrismTestUtil.displayCollection; import static com.evolveum.midpoint.prism.util.PrismTestUtil.getPrismContext; -import java.io.IOException; +import static org.testng.AssertJUnit.fail; + import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import javax.annotation.PostConstruct; import com.evolveum.midpoint.prism.PrismContext; @@ -34,12 +36,12 @@ import com.evolveum.midpoint.util.caching.CachePerformanceCollector; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; -import org.xml.sax.SAXException; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.query.ObjectQuery; @@ -73,46 +75,51 @@ public class TestRepositoryCache extends AbstractSpringTest implements InfraTest @Autowired GlobalObjectCache globalObjectCache; @Autowired GlobalVersionCache globalVersionCache; @Autowired GlobalQueryCache globalQueryCache; + @Autowired PrismContext prismContext; + + @SuppressWarnings("unused") // used when heap dumps are uncommented + private final long identifier = System.currentTimeMillis(); @BeforeSuite - public void setup() throws SchemaException, SAXException, IOException { + public void setup() { PrettyPrinter.setDefaultNamespacePrefix(MidPointConstants.NS_MIDPOINT_PUBLIC_PREFIX); - PrismTestUtil.resetPrismContext(MidPointPrismContextFactory.FACTORY); } @PostConstruct public void initialize() throws SchemaException { + PrismTestUtil.setPrismContext(prismContext); + OperationResult initResult = new OperationResult(CLASS_DOT + "setup"); repositoryCache.postInit(initResult); } @Test - public void testGetUser() throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { + public void test100GetUser() throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { testGetUncachedObject(UserType.class); } @Test - public void testGetSystemConfiguration() throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { + public void test110GetSystemConfiguration() throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { testGetCachedObject(SystemConfigurationType.class); } @Test - public void testSearchUsers() throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { + public void test200SearchUsers() throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { testSearchUncachedObjects(UserType.class); } @Test - public void testSearchArchetypes() throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { + public void test210SearchArchetypes() throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { testSearchCachedObjects(ArchetypeType.class); } @Test - public void testSearchUsersIterative() throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { + public void test220SearchUsersIterative() throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { testSearchUncachedObjectsIterative(UserType.class); } @Test - public void testSearchArchetypesIterative() throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { + public void test230SearchArchetypesIterative() throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { testSearchCachedObjectsIterative(ArchetypeType.class); } @@ -120,7 +127,7 @@ public void testSearchArchetypesIterative() throws SchemaException, ObjectNotFou * MID-6250 */ @Test - public void testModifyInIterativeSearch() throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { + public void test300ModifyInIterativeSearch() throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { given(); PrismContext prismContext = getPrismContext(); OperationResult result = createOperationResult(); @@ -172,7 +179,7 @@ public void testModifyInIterativeSearch() throws SchemaException, ObjectNotFound * MID-6250 */ @Test - public void testAddInIterativeSearch() throws SchemaException, ObjectAlreadyExistsException { + public void test310AddInIterativeSearch() throws SchemaException, ObjectAlreadyExistsException { given(); PrismContext prismContext = getPrismContext(); OperationResult result = createOperationResult(); @@ -223,7 +230,7 @@ public void testAddInIterativeSearch() throws SchemaException, ObjectAlreadyExis * MID-6250 */ @Test - public void testSearchObjectsIterativeSlow() throws ObjectAlreadyExistsException, SchemaException, ObjectNotFoundException { + public void test320SearchObjectsIterativeSlow() throws ObjectAlreadyExistsException, SchemaException, ObjectNotFoundException { OperationResult result = createOperationResult(); deleteExistingObjects(ArchetypeType.class, result); @@ -268,7 +275,7 @@ public void testSearchObjectsIterativeSlow() throws ObjectAlreadyExistsException } @Test - public void testSearchObjectsOverSize() throws ObjectAlreadyExistsException, SchemaException, ObjectNotFoundException { + public void test330SearchObjectsOverSize() throws ObjectAlreadyExistsException, SchemaException, ObjectNotFoundException { OperationResult result = createOperationResult(); deleteExistingObjects(ArchetypeType.class, result); @@ -291,6 +298,75 @@ public void testSearchObjectsOverSize() throws ObjectAlreadyExistsException, Sch assertThat(data.overSizedQueries.get()).as("over-sized counter").isEqualTo(2); // search + searchIterative } + // Must be executed last, because naive deletion such large number of archetypes fails on OOM + @Test + public void test900HeapUsage() throws Exception { + OperationResult result = new OperationResult("testHeapUsage"); + + int size = 2_000_000; + int count = 300; + + // 50 is the default "step" in paged iterative search, so we can expect we always have 50 objects in memory + // And "times 2" is the safety margin. It might or might not be sufficient, as System.gc() is not guaranteed to + // really execute the garbage collection (only suggests JVM to do it). + long tolerance = (50 * size) * 2; + + showMemory("Initial"); + dumpHeap("initial"); + + deleteExistingObjects(ArchetypeType.class, result); + generateLargeObjects(ArchetypeType.class, size, count, result); + showMemory("After generation"); + dumpHeap("after-generation"); + + long usedBefore = getMemoryUsed(); + AtomicInteger seen = new AtomicInteger(); + AtomicLong usedInLastIteration = new AtomicLong(); + repositoryCache.searchObjectsIterative(ArchetypeType.class, null, + (object, parentResult) -> { + if (seen.incrementAndGet() % 100 == 0) { + showMemory("After seeing " + seen.get() + " objects"); + } + if (seen.get() == count) { + usedInLastIteration.set(getMemoryUsed()); + dumpHeap("last-iteration"); + } + return true; + }, null, true, result); + showMemory("Final"); + dumpHeap("final"); + + long difference = usedInLastIteration.get() - usedBefore; + display(String.format("Difference: %,d KB (tolerating %,d KB)", difference / 1024, tolerance / 1024)); + if (difference > tolerance) { + fail("Used too much memory during iterative search: " + difference / 1024 + " KB"); + } + } + + private void showMemory(String desc) { + long used = getMemoryUsed(); + display(String.format("%s: %,d used (%,d KB)%n", desc, used, used / 1024)); + } + + private long getMemoryUsed() { + System.gc(); + return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + } + + @SuppressWarnings("unused") + private void dumpHeap(String desc) { + // Enable when needed +// try { +// HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy(ManagementFactory.getPlatformMBeanServer(), +// "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class); +// display("Generating heap dump: " + desc + "..."); +// mxBean.dumpHeap("heap-" + identifier + "-" + desc + ".hprof", true); +// display("Done"); +// } catch (IOException e) { +// throw new IllegalStateException(e); +// } + } + private void testGetUncachedObject(Class objectClass) throws ObjectAlreadyExistsException, SchemaException, ObjectNotFoundException { testGetObject(objectClass, false); } @@ -546,6 +622,22 @@ private Set> generateObjects(Class obje return objects; } + private void generateLargeObjects(Class objectClass, int size, int count, OperationResult result) + throws SchemaException, + ObjectAlreadyExistsException { + for (int i = 0; i < count; i++) { + PrismObject object = getPrismContext().createObject(objectClass); + object.asObjectable() + .name(PolyStringType.fromOrig("T:" + i)) + .description(StringUtils.repeat('#', size)); + repositoryCache.addObject(object, null, result); + + if ((i+1) % 100 == 0) { + showMemory("After generating " + (i+1) + " objects"); + } + } + } + private void deleteExistingObjects(Class objectClass, OperationResult result) throws SchemaException, ObjectNotFoundException { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlAuditServiceImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlAuditServiceImpl.java index ce8736a8a57..d72a2bcff59 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlAuditServiceImpl.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlAuditServiceImpl.java @@ -17,6 +17,10 @@ import javax.persistence.criteria.CriteriaQuery; import javax.xml.datatype.Duration; +import com.evolveum.midpoint.prism.util.CloneUtil; + +import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationAuditType; + import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; import org.hibernate.FlushMode; @@ -67,11 +71,11 @@ */ public class SqlAuditServiceImpl extends SqlBaseService implements AuditService { - public static final String OP_CLEANUP_AUDIT_MAX_AGE = "cleanupAuditMaxAge"; - public static final String OP_CLEANUP_AUDIT_MAX_RECORDS = "cleanupAuditMaxRecords"; - public static final String OP_LIST_RECORDS = "listRecords"; - public static final String OP_LIST_RECORDS_ATTEMPT = "listRecordsAttempt"; - public static final String OP_LOAD_AUDIT_DELTA = "loadAuditDelta"; + private static final String OP_CLEANUP_AUDIT_MAX_AGE = "cleanupAuditMaxAge"; + private static final String OP_CLEANUP_AUDIT_MAX_RECORDS = "cleanupAuditMaxRecords"; + private static final String OP_LIST_RECORDS = "listRecords"; + private static final String OP_LIST_RECORDS_ATTEMPT = "listRecordsAttempt"; + private static final String OP_LOAD_AUDIT_DELTA = "loadAuditDelta"; @Autowired private BaseHelper baseHelper; @@ -82,7 +86,9 @@ public class SqlAuditServiceImpl extends SqlBaseService implements AuditService private static final String QUERY_MAX_RESULT = "setMaxResults"; private static final String QUERY_FIRST_RESULT = "setFirstResult"; - private Map customColumn = new HashMap<>(); + private final Map customColumn = new HashMap<>(); + + private volatile SystemConfigurationAuditType auditConfiguration; public SqlAuditServiceImpl(SqlRepositoryFactory repositoryFactory) { super(repositoryFactory); @@ -201,10 +207,10 @@ private void reindexEntryAttempt(AuditEventRecord record) { Session session = baseHelper.beginTransaction(); try { - RAuditEventRecord reindexed = RAuditEventRecord.toRepo(record, getPrismContext(), null); - //TODO FIXME temporary hack, merge will eventyually load the object to the session if there isn't one, + RAuditEventRecord reindexed = RAuditEventRecord.toRepo(record, getPrismContext(), null, auditConfiguration); + //TODO FIXME temporary hack, merge will eventually load the object to the session if there isn't one, // but in this case we force loading object because of "objectDeltaOperation". There is some problem probably - // during serializing/deserializing which causes constraint violation on priamry key.. + // during serializing/deserializing which causes constraint violation on primary key.. RAuditEventRecord rRecord = session.load(RAuditEventRecord.class, record.getRepoId()); rRecord.getChangedItems().clear(); rRecord.getChangedItems().addAll(reindexed.getChangedItems()); @@ -464,7 +470,7 @@ private void auditAttempt(AuditEventRecord record) { SingleSqlQuery deltaQuery; try { - deltaQuery = RObjectDeltaOperation.toRepo(id, delta, getPrismContext()); + deltaQuery = RObjectDeltaOperation.toRepo(id, delta, getPrismContext(), auditConfiguration); deltaBatchQuery.addQueryForBatch(deltaQuery); } catch (DtoTranslationException e) { baseHelper.handleGeneralCheckedException(e, session, null); @@ -844,9 +850,7 @@ public long countObjects(String query, Map params) { SelectQueryBuilder queryBuilder = new SelectQueryBuilder(database, basicQuery); setParametersToQuery(queryBuilder, params); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("List records attempt\n processed query: {}", queryBuilder); - } + LOGGER.trace("List records attempt\n processed query: {}", queryBuilder); try (PreparedStatement stmt = queryBuilder.build().createPreparedStatement(connection)) { ResultSet resultList = stmt.executeQuery(); @@ -876,4 +880,8 @@ public Map getCustomColumn() { return customColumn; } + @Override + public void applyAuditConfiguration(SystemConfigurationAuditType configuration) { + this.auditConfiguration = CloneUtil.clone(configuration); + } } diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SystemConfigurationChangeDispatcherImpl.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SystemConfigurationChangeDispatcherImpl.java index e217a225d57..e42785c6aae 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SystemConfigurationChangeDispatcherImpl.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SystemConfigurationChangeDispatcherImpl.java @@ -7,6 +7,7 @@ package com.evolveum.midpoint.repo.sql; +import com.evolveum.midpoint.audit.api.AuditService; import com.evolveum.midpoint.common.LoggingConfigurationManager; import com.evolveum.midpoint.common.ProfilingConfigurationManager; import com.evolveum.midpoint.common.configuration.api.MidpointConfiguration; @@ -37,7 +38,7 @@ import java.util.HashSet; /** - * @author mederly + * Dispatches "system configuration changed" events to relevant objects. */ @Component public class SystemConfigurationChangeDispatcherImpl implements SystemConfigurationChangeDispatcher { @@ -45,6 +46,7 @@ public class SystemConfigurationChangeDispatcherImpl implements SystemConfigurat private static final Trace LOGGER = TraceManager.getTrace(SystemConfigurationChangeDispatcherImpl.class); @Autowired private RepositoryService repositoryService; + @Autowired(required = false) private AuditService auditService; @Autowired private PrismContext prismContext; @Autowired private RelationRegistry relationRegistry; @Autowired private MidpointConfiguration midpointConfiguration; @@ -95,6 +97,7 @@ public synchronized void dispatch(boolean ignoreVersion, boolean allowNotFound, applyRemoteHostAddressHeadersConfiguration(configuration); applyPolyStringNormalizerConfiguration(configuration); applyFullTextSearchConfiguration(configuration); + applyAuditConfiguration(configuration); applyRelationsConfiguration(configuration); applyOperationResultHandlingConfiguration(configuration); applyCachingConfiguration(configuration); @@ -164,6 +167,17 @@ private void applyFullTextSearchConfiguration(SystemConfigurationType configurat } } + private void applyAuditConfiguration(SystemConfigurationType configuration) { + try { + if (auditService != null) { + auditService.applyAuditConfiguration(configuration.getAudit()); + } + } catch (Throwable t) { + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't apply audit configuration", t); + lastVersionApplied = null; + } + } + private void applyRelationsConfiguration(SystemConfigurationType configuration) { try { relationRegistry.applyRelationsConfiguration(configuration); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/audit/RAuditEventRecord.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/audit/RAuditEventRecord.java index 850c71d3960..69d8d4b10b1 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/audit/RAuditEventRecord.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/audit/RAuditEventRecord.java @@ -30,6 +30,8 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationAuditType; + import org.apache.commons.lang.Validate; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.ForeignKey; @@ -504,7 +506,8 @@ public int hashCode() { changedItems, resourceOids, propertyValues, referenceValues, result); } - public static RAuditEventRecord toRepo(AuditEventRecord record, PrismContext prismContext, Boolean isTransient) + public static RAuditEventRecord toRepo(AuditEventRecord record, PrismContext prismContext, Boolean isTransient, + SystemConfigurationAuditType auditConfiguration) throws DtoTranslationException { Validate.notNull(record, "Audit event record must not be null."); @@ -588,7 +591,7 @@ public static RAuditEventRecord toRepo(AuditEventRecord record, PrismContext pri } } - RObjectDeltaOperation rDelta = RObjectDeltaOperation.toRepo(repo, delta, prismContext); + RObjectDeltaOperation rDelta = RObjectDeltaOperation.toRepo(repo, delta, prismContext, auditConfiguration); rDelta.setTransient(true); rDelta.setRecord(repo); repo.getDeltas().add(rDelta); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/audit/RObjectDeltaOperation.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/audit/RObjectDeltaOperation.java index 17192aa3255..7f338d3dbb4 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/audit/RObjectDeltaOperation.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/audit/RObjectDeltaOperation.java @@ -8,10 +8,15 @@ package com.evolveum.midpoint.repo.sql.data.audit; import static com.evolveum.midpoint.repo.sql.data.audit.RObjectDeltaOperation.COLUMN_RECORD_ID; +import static com.evolveum.midpoint.schema.util.SystemConfigurationAuditUtil.isEscapingInvalidCharacters; import java.sql.ResultSet; import javax.persistence.*; +import com.evolveum.midpoint.prism.SerializationOptions; + +import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationAuditType; + import org.hibernate.annotations.ForeignKey; import org.jetbrains.annotations.NotNull; @@ -261,7 +266,7 @@ public int hashCode() { } public static RObjectDeltaOperation toRepo(RAuditEventRecord record, ObjectDeltaOperation operation, - PrismContext prismContext) throws DtoTranslationException { + PrismContext prismContext, SystemConfigurationAuditType auditConfiguration) throws DtoTranslationException { RObjectDeltaOperation auditDelta = new RObjectDeltaOperation(); auditDelta.setRecord(record); @@ -269,7 +274,9 @@ public static RObjectDeltaOperation toRepo(RAuditEventRecord record, ObjectDelta if (operation.getObjectDelta() != null) { ObjectDelta delta = operation.getObjectDelta(); - String xmlDelta = DeltaConvertor.toObjectDeltaTypeXml(delta, DeltaConversionOptions.createSerializeReferenceNames()); + DeltaConversionOptions options = DeltaConversionOptions.createSerializeReferenceNames(); + options.setEscapeInvalidCharacters(isEscapingInvalidCharacters(auditConfiguration)); + String xmlDelta = DeltaConvertor.toObjectDeltaTypeXml(delta, options); byte[] data = RUtil.getByteArrayFromXml(xmlDelta, true); auditDelta.setDelta(data); @@ -294,7 +301,7 @@ public static RObjectDeltaOperation toRepo(RAuditEventRecord record, ObjectDelta } public static SingleSqlQuery toRepo(Long recordId, ObjectDeltaOperation operation, - PrismContext prismContext) throws DtoTranslationException { + PrismContext prismContext, SystemConfigurationAuditType auditConfiguration) throws DtoTranslationException { InsertQueryBuilder queryBuilder = new InsertQueryBuilder(TABLE_NAME); queryBuilder.addParameter(COLUMN_RECORD_ID, recordId, true); @@ -304,7 +311,9 @@ public static SingleSqlQuery toRepo(Long recordId, ObjectDeltaOperation operatio if (operation.getObjectDelta() != null) { ObjectDelta delta = operation.getObjectDelta(); - String xmlDelta = DeltaConvertor.toObjectDeltaTypeXml(delta, DeltaConversionOptions.createSerializeReferenceNames()); + DeltaConversionOptions options = DeltaConversionOptions.createSerializeReferenceNames(); + options.setEscapeInvalidCharacters(isEscapingInvalidCharacters(auditConfiguration)); + String xmlDelta = DeltaConvertor.toObjectDeltaTypeXml(delta, options); deltaData = RUtil.getByteArrayFromXml(xmlDelta, true); queryBuilder.addParameter(DELTA_COLUMN_NAME, deltaData); queryBuilder.addParameter(DELTA_OID_COLUMN_NAME, delta.getOid()); @@ -323,7 +332,9 @@ public static SingleSqlQuery toRepo(Long recordId, ObjectDeltaOperation operatio } else { queryBuilder.addParameter(STATUS_COLUMN_NAME, RUtil.getRepoEnumValue(jaxb.getStatus(), ROperationResultStatus.class)); try { - String full = prismContext.xmlSerializer().serializeRealValue(jaxb, SchemaConstantsGenerated.C_OPERATION_RESULT); + String full = prismContext.xmlSerializer() + .options(SerializationOptions.createEscapeInvalidCharacters()) + .serializeRealValue(jaxb, SchemaConstantsGenerated.C_OPERATION_RESULT); fullResultData = RUtil.getByteArrayFromXml(full, true); queryBuilder.addParameter(FULL_RESULT_COLUMN_NAME, fullResultData); } catch (Exception ex) { diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedReference.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedReference.java index e5e5c8610be..e48fd9c5bfe 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedReference.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/data/common/embedded/REmbeddedReference.java @@ -126,9 +126,6 @@ public static REmbeddedReference fromJaxb(ObjectReferenceType jaxb, REmbeddedRef RelationRegistry relationRegistry) { Validate.notNull(repo, "Repo object must not be null."); Validate.notNull(jaxb, "JAXB object must not be null."); - if (jaxb.getFilter() == null) { - Validate.notEmpty(jaxb.getOid(), "Target oid must not be null."); - } repo.setType(ClassMapper.getHQLTypeForQName(jaxb.getType())); repo.setRelation(qnameToString(relationRegistry.normalizeRelation(jaxb.getRelation()))); repo.setTargetOid(jaxb.getOid()); diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/TestResource.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/TestResource.java index cc5d9e19bb3..3ffc1c64b52 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/TestResource.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/TestResource.java @@ -35,4 +35,8 @@ public String getNameOrig() { public T getObjectable() { return object.asObjectable(); } + + public Class getObjectClass() { + return object.getCompileTimeClass(); + } } diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/AssignmentAsserter.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/AssignmentAsserter.java index 787c9efed7d..0bce99de202 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/AssignmentAsserter.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/AssignmentAsserter.java @@ -6,6 +6,7 @@ */ package com.evolveum.midpoint.test.asserter; +import static org.assertj.core.api.Assertions.assertThat; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertNotNull; @@ -16,6 +17,7 @@ import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.test.IntegrationTestTools; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; /** @@ -72,6 +74,15 @@ public AssignmentAsserter assertRole(String expectedOid) { return this; } + public AssignmentAsserter assertResource(String expectedOid) { + ConstructionType construction = assignment.getConstruction(); + assertThat(construction).as("construction in " + desc()).isNotNull(); + assertThat(construction.getResourceRef()).as("resourceRef in construction in " + desc()).isNotNull(); + assertThat(construction.getResourceRef().getOid()).as("resource OID in construction in " + desc()) + .isEqualTo(expectedOid); + return this; + } + public AssignmentAsserter assertSubtype(String expected) { List subtypes = assignment.getSubtype(); if (subtypes.isEmpty()) { diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/AssignmentFinder.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/AssignmentFinder.java index 0f5c631629a..75c91a5c488 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/AssignmentFinder.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/AssignmentFinder.java @@ -30,6 +30,7 @@ public class AssignmentFinder assignmentsAsserter) { this.assignmentsAsserter = assignmentsAsserter; @@ -50,12 +51,16 @@ public AssignmentFinder targetType(QName targetType) { return this; } + public AssignmentFinder resourceOid(String resourceOid) { + this.resourceOid = resourceOid; + return this; + } + public AssignmentAsserter> find() throws ObjectNotFoundException, SchemaException { AssignmentType found = null; PrismObject foundTarget = null; for (AssignmentType assignment: assignmentsAsserter.getAssignments()) { PrismObject assignmentTarget = null; -// PrismObject assignmentTarget = assignmentsAsserter.getTarget(assignment.getOid()); if (matches(assignment, assignmentTarget)) { if (found == null) { found = assignment; @@ -125,6 +130,12 @@ private boolean matches(AssignmentType assignment, PrismObject targetObject) } } + if (resourceOid != null) { + if (assignment.getConstruction() == null || assignment.getConstruction().getResourceRef() == null + || !resourceOid.equals(assignment.getConstruction().getResourceRef().getOid())) { + return false; + } + } // TODO: more criteria return true; } diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/DummyObjectAsserter.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/DummyObjectAsserter.java index 2d85303ca2b..6bd9f3e6df8 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/DummyObjectAsserter.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/DummyObjectAsserter.java @@ -106,7 +106,7 @@ protected String desc() { if (dummyResourceName == null) { return descWithDetails(dummyObject) + " on default dummy resource"; } else { - return descWithDetails(dummyObject.toString()) + " on dummy resource '"+dummyResourceName+"'"; + return descWithDetails(dummyObject) + " on dummy resource '"+dummyResourceName+"'"; } } diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/ResourceAsserter.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/ResourceAsserter.java index 257403dda09..87805cbfe6a 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/ResourceAsserter.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/ResourceAsserter.java @@ -10,6 +10,8 @@ import static com.evolveum.midpoint.prism.Containerable.asPrismContainerValue; +import static org.testng.AssertJUnit.assertNull; + import org.w3c.dom.Element; import com.evolveum.midpoint.prism.PrismContainer; @@ -90,6 +92,12 @@ public ResourceAsserter assertHasSchema() { return this; } + public ResourceAsserter assertHasNoSchema() { + Element schemaElement = ResourceTypeUtil.getResourceXsdSchema(getObject()); + assertNull("Schema present in " + desc(), schemaElement); + return this; + } + @Override public ResourceAsserter display() { super.display(); diff --git a/repo/system-init/src/main/java/com/evolveum/midpoint/init/AuditServiceProxy.java b/repo/system-init/src/main/java/com/evolveum/midpoint/init/AuditServiceProxy.java index 24f9eca7026..060c8c9f83f 100644 --- a/repo/system-init/src/main/java/com/evolveum/midpoint/init/AuditServiceProxy.java +++ b/repo/system-init/src/main/java/com/evolveum/midpoint/init/AuditServiceProxy.java @@ -32,6 +32,8 @@ import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.CleanupPolicyType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationAuditType; + import org.apache.commons.lang.Validate; import org.jetbrains.annotations.Nullable; import org.springframework.beans.factory.annotation.Autowired; @@ -67,7 +69,7 @@ public class AuditServiceProxy implements AuditService, AuditServiceRegistry { @Autowired private PrismContext prismContext; @Autowired private SchemaHelper schemaHelper; - private List services = new Vector<>(); + private final List services = new Vector<>(); @Override public void audit(AuditEventRecord record, Task task) { @@ -253,4 +255,9 @@ public boolean supportsRetrieval() { } return false; } + + @Override + public void applyAuditConfiguration(SystemConfigurationAuditType configuration) { + services.forEach(service -> service.applyAuditConfiguration(configuration)); + } } diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/tracing/TracerImpl.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/tracing/TracerImpl.java index bd9a08378e6..70235b3480c 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/tracing/TracerImpl.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/tracing/TracerImpl.java @@ -124,7 +124,10 @@ public void storeTrace(Task task, OperationResult result, @Nullable OperationRes long start = System.currentTimeMillis(); TracingOutputType tracingOutput = createTracingOutput(task, result, tracingProfile); String xml = prismContext.xmlSerializer() - .options(SerializationOptions.createSerializeReferenceNames()) + .options( + SerializationOptions + .createSerializeReferenceNames() + .escapeInvalidCharacters(true)) .serializeRealValue(tracingOutput); if (zip) { MiscUtil.writeZipFile(file, ZIP_ENTRY_NAME, xml, StandardCharsets.UTF_8); diff --git a/testing/conntest/pom.xml b/testing/conntest/pom.xml index 7f5d7a521ed..fd34519f9d4 100644 --- a/testing/conntest/pom.xml +++ b/testing/conntest/pom.xml @@ -1,239 +1,239 @@ - - - - - 4.0.0 - - - testing - com.evolveum.midpoint.testing - 4.2-SNAPSHOT - - - conntest - - midPoint Testing - Resource Connection Tests - - - - com.evolveum.midpoint.infra - util - 4.2-SNAPSHOT - - - com.evolveum.midpoint.infra - schema - 4.2-SNAPSHOT - - - com.evolveum.midpoint.infra - prism-api - 4.2-SNAPSHOT - - - com.evolveum.midpoint.infra - prism-impl - 4.2-SNAPSHOT - runtime - - - com.evolveum.midpoint.infra - common - 4.2-SNAPSHOT - - - com.evolveum.midpoint.repo - repo-api - 4.2-SNAPSHOT - - - com.evolveum.midpoint.repo - task-api - 4.2-SNAPSHOT - - - com.evolveum.midpoint.provisioning - provisioning-api - 4.2-SNAPSHOT - - - com.evolveum.midpoint.model - model-api - 4.2-SNAPSHOT - - - com.evolveum.midpoint.model - model-impl - 4.2-SNAPSHOT - runtime - - - com.evolveum.midpoint.model - model-test - 4.2-SNAPSHOT - - - com.evolveum.midpoint.provisioning - provisioning-impl - 4.2-SNAPSHOT - runtime - - - com.evolveum.midpoint.provisioning - ucf-impl-builtin - 4.2-SNAPSHOT - runtime - - - com.evolveum.midpoint.repo - task-quartz-impl - 4.2-SNAPSHOT - runtime - - - com.evolveum.midpoint.repo - audit-impl - 4.2-SNAPSHOT - runtime - - - com.evolveum.midpoint.repo - security-enforcer-impl - 4.2-SNAPSHOT - runtime - - - com.evolveum.midpoint.repo - security-impl - 4.2-SNAPSHOT - runtime - - - com.evolveum.midpoint.repo - repo-common - 4.2-SNAPSHOT - runtime - - - com.evolveum.midpoint.repo - repo-test-util - 4.2-SNAPSHOT - - - org.apache.directory.api - api-all - - - - commons-lang - commons-lang - - - org.springframework - spring-beans - - - - - org.testng - testng - test - - - com.evolveum.midpoint.tools - test-ng - test - - - com.evolveum.polygon - connector-ldap - test - - - - org.slf4j - slf4j-jdk14 - - - - - com.evolveum.polygon - connector-powershell - test - - - com.evolveum.polygon - connector-databasetable - test - - - com.evolveum.midpoint.infra - test-util - test - - - com.evolveum.midpoint.repo - repo-sql-impl - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint - midpoint-localization - ${project.version} - test - - - com.evolveum.midpoint.repo - repo-sql-impl-test - 4.2-SNAPSHOT - test - - - org.springframework - spring-test - test - - - org.springframework - spring-aspects - test - - - com.evolveum.midpoint.repo - system-init - 4.2-SNAPSHOT - test - - - javax.servlet - javax.servlet-api - test - - - - - - - maven-surefire-plugin - - - true - alphabetical - - - - maven-failsafe-plugin - - ${skipConnTests} - alphabetical - - - - - + + + + + 4.0.0 + + + testing + com.evolveum.midpoint.testing + 4.2-SNAPSHOT + + + conntest + + midPoint Testing - Resource Connection Tests + + + + com.evolveum.midpoint.infra + util + 4.2-SNAPSHOT + + + com.evolveum.midpoint.infra + schema + 4.2-SNAPSHOT + + + com.evolveum.midpoint.infra + prism-api + 4.2-SNAPSHOT + + + com.evolveum.midpoint.infra + prism-impl + 4.2-SNAPSHOT + runtime + + + com.evolveum.midpoint.infra + common + 4.2-SNAPSHOT + + + com.evolveum.midpoint.repo + repo-api + 4.2-SNAPSHOT + + + com.evolveum.midpoint.repo + task-api + 4.2-SNAPSHOT + + + com.evolveum.midpoint.provisioning + provisioning-api + 4.2-SNAPSHOT + + + com.evolveum.midpoint.model + model-api + 4.2-SNAPSHOT + + + com.evolveum.midpoint.model + model-impl + 4.2-SNAPSHOT + runtime + + + com.evolveum.midpoint.model + model-test + 4.2-SNAPSHOT + + + com.evolveum.midpoint.provisioning + provisioning-impl + 4.2-SNAPSHOT + runtime + + + com.evolveum.midpoint.provisioning + ucf-impl-builtin + 4.2-SNAPSHOT + runtime + + + com.evolveum.midpoint.repo + task-quartz-impl + 4.2-SNAPSHOT + runtime + + + com.evolveum.midpoint.repo + audit-impl + 4.2-SNAPSHOT + runtime + + + com.evolveum.midpoint.repo + security-enforcer-impl + 4.2-SNAPSHOT + runtime + + + com.evolveum.midpoint.repo + security-impl + 4.2-SNAPSHOT + runtime + + + com.evolveum.midpoint.repo + repo-common + 4.2-SNAPSHOT + runtime + + + com.evolveum.midpoint.repo + repo-test-util + 4.2-SNAPSHOT + + + org.apache.directory.api + api-all + + + + org.apache.commons + commons-lang3 + + + org.springframework + spring-beans + + + + + org.testng + testng + test + + + com.evolveum.midpoint.tools + test-ng + test + + + com.evolveum.polygon + connector-ldap + test + + + + org.slf4j + slf4j-jdk14 + + + + + com.evolveum.polygon + connector-powershell + test + + + com.evolveum.polygon + connector-databasetable + test + + + com.evolveum.midpoint.infra + test-util + test + + + com.evolveum.midpoint.repo + repo-sql-impl + 4.2-SNAPSHOT + test + + + com.evolveum.midpoint + midpoint-localization + ${project.version} + test + + + com.evolveum.midpoint.repo + repo-sql-impl-test + 4.2-SNAPSHOT + test + + + org.springframework + spring-test + test + + + org.springframework + spring-aspects + test + + + com.evolveum.midpoint.repo + system-init + 4.2-SNAPSHOT + test + + + javax.servlet + javax.servlet-api + test + + + + + + + maven-surefire-plugin + + + true + alphabetical + + + + maven-failsafe-plugin + + ${skipConnTests} + alphabetical + + + + + diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractLdapConnTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractLdapConnTest.java index a4898e7dab7..7128cf2d701 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractLdapConnTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractLdapConnTest.java @@ -16,7 +16,7 @@ import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; -import org.apache.commons.lang.mutable.MutableInt; +import org.apache.commons.lang3.mutable.MutableInt; import org.apache.directory.api.ldap.model.entry.Entry; import org.apache.directory.api.ldap.model.exception.LdapException; import org.springframework.beans.factory.annotation.Autowired; diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java index 50157dfda60..bfccc2c70fb 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java @@ -1,2435 +1,2435 @@ -/* - * Copyright (c) 2015-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.testing.conntest.ad; - -import static org.testng.AssertJUnit.*; - -import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_CREDENTIALS_PASSWORD_VALUE; - -import java.io.File; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.Collection; -import java.util.List; -import javax.xml.datatype.XMLGregorianCalendar; -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.prism.PrismProperty; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; - -import org.apache.commons.lang.StringUtils; -import org.apache.directory.api.ldap.model.cursor.CursorException; -import org.apache.directory.api.ldap.model.entry.DefaultEntry; -import org.apache.directory.api.ldap.model.entry.Entry; -import org.apache.directory.api.ldap.model.exception.LdapException; -import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; -import org.apache.directory.api.ldap.model.name.Ava; -import org.apache.directory.api.ldap.model.name.Rdn; -import org.apache.directory.ldap.client.api.LdapNetworkConnection; -import org.testng.AssertJUnit; -import org.testng.annotations.Listeners; -import org.testng.annotations.Test; - -import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; -import com.evolveum.midpoint.model.api.ModelExecuteOptions; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.prism.delta.PropertyDelta; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.ObjectPaging; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.prism.query.OrderDirection; -import com.evolveum.midpoint.prism.util.PrismAsserts; -import com.evolveum.midpoint.prism.util.PrismTestUtil; -import com.evolveum.midpoint.prism.xml.XmlTypeConverter; -import com.evolveum.midpoint.schema.SearchResultList; -import com.evolveum.midpoint.schema.SearchResultMetadata; -import com.evolveum.midpoint.schema.constants.MidPointConstants; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.internals.InternalCounters; -import com.evolveum.midpoint.schema.processor.ResourceAttribute; -import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; -import com.evolveum.midpoint.schema.processor.ResourceSchema; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.util.MiscSchemaUtil; -import com.evolveum.midpoint.schema.util.ObjectQueryUtil; -import com.evolveum.midpoint.schema.util.ShadowUtil; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.test.IntegrationTestTools; -import com.evolveum.midpoint.test.util.MidPointTestConstants; -import com.evolveum.midpoint.test.util.TestUtil; -import com.evolveum.midpoint.testing.conntest.AbstractLdapTest; -import com.evolveum.midpoint.testing.conntest.UserLdapConnectionConfig; -import com.evolveum.midpoint.util.MiscUtil; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SystemException; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; -import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; - -/** - * @author semancik - */ -@Listeners({ com.evolveum.midpoint.tools.testng.AlphabeticalMethodInterceptor.class }) -public abstract class AbstractAdLdapMultidomainTest extends AbstractLdapTest - implements AdTestMixin { - - protected static final File TEST_DIR = new File(MidPointTestConstants.TEST_RESOURCES_DIR, "ad-ldap-multidomain"); - - protected static final File ROLE_PIRATES_FILE = new File(TEST_DIR, "role-pirate.xml"); - protected static final String ROLE_PIRATES_OID = "5dd034e8-41d2-11e5-a123-001e8c717e5b"; - - protected static final File ROLE_SUBMISSIVE_FILE = new File(TEST_DIR, "role-submissive.xml"); - protected static final String ROLE_SUBMISSIVE_OID = "0c0c81b2-d0a1-11e5-b51e-0309a826745e"; - - protected static final File ROLE_META_ORG_FILE = new File(TEST_DIR, "role-meta-org.xml"); - protected static final String ROLE_META_ORG_OID = "f2ad0ace-45d7-11e5-af54-001e8c717e5b"; - - protected static final File ROLE_META_ORG_GROUP_FILE = new File(TEST_DIR, "role-meta-org-group.xml"); - protected static final String ROLE_META_ORG_GROUP_OID = "c5d3294a-0d8e-11e7-bd9d-ff848c2e7e3f"; - - protected static final String ACCOUNT_JACK_SAM_ACCOUNT_NAME = "jack"; - protected static final String ACCOUNT_JACK_SID = "S-1-5-21-3305462238-3617280118-659738602-4878"; - protected static final String ACCOUNT_JACK_FULL_NAME = "Jack Sparrow"; - protected static final String ACCOUNT_JACK_PASSWORD = "qwe.123"; - - protected static final String ACCOUNT_HT_UID = "ht"; - protected static final String ACCOUNT_HT_CN = "Herman Toothrot"; - protected static final String ACCOUNT_HT_GIVENNAME = "Herman"; - protected static final String ACCOUNT_HT_SN = "Toothrot"; - protected static final String ACCOUNT_HT_SN_MODIFIED = "Torquemeda Marley"; - - protected static final String ACCOUNT_HTM_UID = "htm"; - protected static final String ACCOUNT_HTM_CN = "Horatio Torquemada Marley"; - - protected static final String USER_CPTBARBOSSA_FULL_NAME = "Captain Hector Barbossa"; - - private static final String GROUP_PIRATES_NAME = "pirates"; - private static final String GROUP_MELEE_ISLAND_NAME = "Mêlée Island"; - private static final String GROUP_MELEE_ISLAND_ALT_NAME = "Alternative Mêlée Island"; - private static final String GROUP_MELEE_ISLAND_PIRATES_NAME = "Mêlée Island Pirates"; - private static final String GROUP_MELEE_ISLAND_PIRATES_DESCRIPTION = "swashbuckle and loot"; - - protected static final int NUMBER_OF_ACCOUNTS = 18; - private static final String ASSOCIATION_GROUP_NAME = "group"; - - private static final String NS_EXTENSION = "http://whatever.com/my"; - private static final QName EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME = new QName(NS_EXTENSION, "showInAdvancedViewOnly"); - - protected static final File USER_SUBMAN_FILE = new File(TEST_DIR, "user-subman.xml"); - private static final String USER_SUBMAN_OID = "910ac45a-8bd6-11e6-9122-ef88d95095f0"; - private static final String USER_SUBMAN_USERNAME = "subman"; - private static final String USER_SUBMAN_GIVEN_NAME = "Sub"; - private static final String USER_SUBMAN_FAMILY_NAME = "Man"; - private static final String USER_SUBMAN_FULL_NAME = "Sub Man"; - private static final String USER_SUBMAN_PASSWORD = "sub.123"; - - private static final String USER_SUBDOG_USERNAME = "subdog"; - private static final String USER_SUBDOG_GIVEN_NAME = "Sub"; - private static final String USER_SUBDOG_FAMILY_NAME = "Dog"; - private static final String USER_SUBDOG_FULL_NAME = "Sub Dog"; - - protected static final File USER_SUBMARINE_FILE = new File(TEST_DIR, "user-submarine.xml"); - private static final String USER_SUBMARINE_OID = "c4377f86-8be9-11e6-8ef5-c3c56ff64b09"; - private static final String USER_SUBMARINE_USERNAME = "submarine"; - private static final String USER_SUBMARINE_GIVEN_NAME = "Sub"; - private static final String USER_SUBMARINE_FAMILY_NAME = "Marine"; - private static final String USER_SUBMARINE_FULL_NAME = "Sub Marine"; - - private static final String INTENT_GROUP = "group"; - private static final String INTENT_OU_TOP = "ou-top"; - - private static final String USER_EMPTYHEAD_NAME = "emptyhead"; - - private static final String PROXY_ADDRES_ADDR_UPCASE = "smpt:ADDR"; - private static final String PROXY_ADDRES_ADDR_LOWCASE = "smpt:addr"; - - private static final String OBJECT_CATEGORY_PERSON = "CN=Person,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com"; - private static final String OBJECT_CATEGORY_GROUP = "CN=Group,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com"; - - private static final String USER_GUYBRUSH_PASSWORD_123 = "wanna.be.a.123"; - private static final String USER_GUYBRUSH_PASSWORD_333 = "wanna.be.a.333"; - - private static final String VERY_STRANGE_PARAMETER = "This iš a véry stándže p§räméteř!"; - - private boolean allowDuplicateSearchResults = false; - - protected String jackAccountOid; - protected String groupPiratesOid; - protected long jackLockoutTimestamp; - protected String accountBarbossaOid; - protected String orgMeleeIslandOid; - protected String groupMeleeIslandOid; - protected String ouMeleeIslandOid; - protected String roleMeleeIslandPiratesOid; - protected String groupMeleeIslandPiratesOid; - - private String accountSubmanOid; - - private String accountSubmarineOid; - - @Override - public String getStartSystemCommand() { - return null; - } - - @Override - public String getStopSystemCommand() { - return null; - } - - @Override - protected File getBaseDir() { - return TEST_DIR; - } - - @Override - protected String getSyncTaskOid() { - return "0f93d8d4-5fb4-11ea-8571-a3f090bf921f"; - } - - @Override - protected boolean useSsl() { - return true; - } - - @Override - protected String getLdapSuffix() { - return "DC=ad,DC=evolveum,DC=com"; - } - - @Override - protected String getLdapBindDn() { - return "CN=midpoint,CN=Users,DC=ad,DC=evolveum,DC=com"; - } - - @Override - protected String getLdapBindPassword() { - return "qwe.123"; - } - - @Override - protected int getSearchSizeLimit() { - return -1; - } - - @Override - public String getPrimaryIdentifierAttributeName() { - return "objectGUID"; - } - - @Override - protected String getPeopleLdapSuffix() { - return "CN=Users," + getLdapSuffix(); - } - - @Override - protected String getGroupsLdapSuffix() { - return "CN=Users," + getLdapSuffix(); - } - - protected String getLdapSubSuffix() { - return "DC=sub,DC=ad,DC=evolveum,DC=com"; - } - - protected String getPeopleLdapSubSuffix() { - return "CN=Users," + getLdapSubSuffix(); - } - - @Override - protected String getLdapAccountObjectClass() { - return "user"; - } - - @Override - protected String getLdapGroupObjectClass() { - return "group"; - } - - @Override - protected String getLdapGroupMemberAttribute() { - return "member"; - } - - private QName getAssociationGroupQName() { - return new QName(MidPointConstants.NS_RI, ASSOCIATION_GROUP_NAME); - } - - @Override - protected boolean allowDuplicateSearchResults() { - return allowDuplicateSearchResults; - } - - @Override - protected boolean isGroupMemberMandatory() { - return false; - } - - protected String getOrgsLdapSuffix() { - return "OU=Org," + getLdapSuffix(); - } - - private UserLdapConnectionConfig getSubLdapConnectionConfig() { - UserLdapConnectionConfig config = new UserLdapConnectionConfig(); - config.setLdapHost("hydra.ad.evolveum.com"); - config.setLdapPort(getLdapServerPort()); - config.setBindDn("CN=midpoint,CN=Users,DC=sub,DC=ad,DC=evolveum,DC=com"); - config.setBindPassword(getLdapBindPassword()); - config.setBaseContext(getLdapSubSuffix()); - return config; - } - - protected abstract File getReconciliationTaskFile(); - - protected abstract String getReconciliationTaskOid(); - - protected String getLdapConnectorClassName() { - return AD_CONNECTOR_TYPE; - } - - @Override - public void initSystem(Task initTask, OperationResult initResult) throws Exception { - super.initSystem(initTask, initResult); - - binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_OBJECT_GUID_NAME); - binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_UNICODE_PWD_NAME); - - // Users - repoAddObjectFromFile(USER_BARBOSSA_FILE, initResult); - repoAddObjectFromFile(USER_GUYBRUSH_FILE, initResult); - repoAddObjectFromFile(USER_SUBMAN_FILE, initResult); - repoAddObjectFromFile(USER_SUBMARINE_FILE, initResult); - - // Roles - repoAddObjectFromFile(ROLE_END_USER_FILE, initResult); - repoAddObjectFromFile(ROLE_PIRATES_FILE, initResult); - repoAddObjectFromFile(ROLE_SUBMISSIVE_FILE, initResult); - repoAddObjectFromFile(ROLE_META_ORG_FILE, initResult); - repoAddObjectFromFile(ROLE_META_ORG_GROUP_FILE, initResult); - - assignRole(USER_BARBOSSA_OID, ROLE_END_USER_OID); - - } - - @Test - public void test000Sanity() throws Exception { - assertLdapPassword(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME, ACCOUNT_JACK_PASSWORD); - cleanupDelete(toAccountDn(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME)); - cleanupDelete(toAccountDn(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME)); - cleanupDelete(toAccountDn(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME)); - cleanupDelete(getSubLdapConnectionConfig(), toAccountSubDn(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME)); - cleanupDelete(getSubLdapConnectionConfig(), toAccountSubDn(USER_SUBDOG_USERNAME, USER_SUBDOG_FULL_NAME)); - cleanupDelete(getSubLdapConnectionConfig(), toAccountSubDn(USER_SUBMARINE_USERNAME, USER_SUBMARINE_FULL_NAME)); - cleanupDelete(toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN)); - cleanupDelete(toAccountDn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN)); - cleanupDelete(toGroupDn(GROUP_MELEE_ISLAND_NAME)); - cleanupDelete(toGroupDn(GROUP_MELEE_ISLAND_ALT_NAME)); - cleanupDelete(toOrgGroupDn(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME)); - cleanupDelete(toOrgGroupDn(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME)); - cleanupDelete(toOrgDn(GROUP_MELEE_ISLAND_NAME)); - cleanupDelete("ou=underMelee," + toOrgDn(GROUP_MELEE_ISLAND_ALT_NAME)); - cleanupDelete(toOrgDn(GROUP_MELEE_ISLAND_ALT_NAME)); - } - - @Test - @Override - public void test020Schema() throws Exception { - // IntegrationTestTools.displayXml("Resource XML", resource); - accountObjectClassDefinition = assertAdResourceSchema(resource, getAccountObjectClass(), prismContext); - assertAdRefinedSchema(resource, getAccountObjectClass()); - assertExchangeSchema(resource, getAccountObjectClass(), prismContext); - - ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); - assertEquals("Unexpected number of schema definitions (limited by generation constraints)", 5, resourceSchema.getDefinitions().size()); - - assertLdapConnectorInstances(1); - } - - @Test - public void test100SeachJackBySamAccountName() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = createSamAccountNameQuery(ACCOUNT_JACK_SAM_ACCOUNT_NAME); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - when(); - SearchResultList> shadows = - modelService.searchObjects(ShadowType.class, query, null, task, result); - - // THEN - then(); - assertSuccess(result); - - assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); - - PrismObject shadow = shadows.get(0); - display("Shadow", shadow); - assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); - assertSid(shadow, ACCOUNT_JACK_SID); - assertObjectCategory(shadow, OBJECT_CATEGORY_PERSON); - jackAccountOid = shadow.getOid(); - -// assertConnectorOperationIncrement(2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = shadows.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(1); - } - - /** - * MID-3730 - */ - @Test - public void test101SeachJackByDn() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - String jackDn = toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME); - ObjectQuery query = createAccountShadowQueryByAttribute("dn", jackDn, resource); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - when(); - SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); - - // THEN - then(); - assertSuccess(result); - - assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); - - PrismObject shadow = shadows.get(0); - display("Shadow", shadow); - assertAccountShadow(shadow, jackDn); - assertSid(shadow, ACCOUNT_JACK_SID); - assertObjectCategory(shadow, OBJECT_CATEGORY_PERSON); - -// assertConnectorOperationIncrement(2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = shadows.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(1); - } - - /** - * Search for non-existent DN should return no results. It should NOT - * throw an error. - *

- * MID-3730 - */ - @Test - public void test102SeachNotExistByDn() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - String dn = toAccountDn("idonoexist", "I am a Fiction"); - ObjectQuery query = createAccountShadowQueryByAttribute("dn", dn, resource); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - when(); - SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); - - // THEN - then(); - assertSuccess(result); - - assertEquals("Unexpected search result: " + shadows, 0, shadows.size()); - -// assertConnectorOperationIncrement(2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - assertLdapConnectorInstances(1); - } - - @Test - public void test105SeachPiratesByCn() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getGroupObjectClass(), prismContext); - ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter("cn", GROUP_PIRATES_NAME), prismContext); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - when(); - SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); - - // THEN - then(); - assertSuccess(result); - - assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); - - PrismObject shadow = shadows.get(0); - display("Shadow", shadow); - groupPiratesOid = shadow.getOid(); - assertObjectCategory(shadow, OBJECT_CATEGORY_GROUP); - -// assertConnectorOperationIncrement(1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = shadows.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(1); - } - - @Test - public void test110GetJack() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - long startOfTestMsTimestamp = getWin32Filetime(System.currentTimeMillis()); - - // WHEN - when(); - PrismObject shadow = modelService.getObject(ShadowType.class, jackAccountOid, null, task, result); - - // THEN - then(); - assertSuccess(result); - - display("Shadow", shadow); - assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); - jackAccountOid = shadow.getOid(); - - IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); - - assertAttribute(shadow, "dn", "CN=Jack Sparrow,CN=Users,DC=ad,DC=evolveum,DC=com"); - assertAttribute(shadow, "cn", ACCOUNT_JACK_FULL_NAME); - assertAttribute(shadow, "sn", "Sparrow"); - assertAttribute(shadow, "description", "The best pirate the world has ever seen"); - assertAttribute(shadow, "sAMAccountName", ACCOUNT_JACK_SAM_ACCOUNT_NAME); - assertObjectCategory(shadow, OBJECT_CATEGORY_PERSON); - List lastLogonValues = ShadowUtil.getAttributeValues(shadow, new QName(getResourceNamespace(), "lastLogon")); - assertEquals("Wrong number of lastLong values: " + lastLogonValues, 1, lastLogonValues.size()); - if (lastLogonValues.get(0) > startOfTestMsTimestamp) { - fail("Wrong lastLogon, expected it to be less than " + startOfTestMsTimestamp + ", but was " + lastLogonValues.get(0)); - } - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - assertLdapConnectorInstances(1); - } - - /** - * No paging. It should return all accounts. - */ - @Test - public void test150SeachAllAccounts() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - SearchResultList> searchResultList = doSearch(query, - NUMBER_OF_ACCOUNTS, task, result); - - // TODO: Why 14? Why not 1? - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 14); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * This is in one block. - */ - @Test - public void test152SeachFirst2Accounts() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(); - paging.setMaxSize(2); - query.setPaging(paging); - - SearchResultList> searchResultList = doSearch(query, 2, task, result); - - // TODO: Why 2? Why not 1? - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - @Test - public void test154SeachFirst11Accounts() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(); - paging.setMaxSize(11); - query.setPaging(paging); - - SearchResultList> searchResultList = doSearch(query, 11, task, result); - - // TODO: Why 2? Why not 1? - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - @Test - public void test162SeachFirst2AccountsOffset0() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(); - paging.setOffset(0); - paging.setMaxSize(2); - query.setPaging(paging); - - SearchResultList> searchResultList = doSearch(query, 2, task, result); - - // TODO: Why 2? Why not 1? - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * There is offset, so VLV should be used. - * No explicit sorting. - */ - @Test - public void test172Search2AccountsOffset1() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(1, 2); - query.setPaging(paging); - - SearchResultList> searchResultList = doSearch(query, 2, task, result); - - // TODO: Why 2? Why not 1? - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * There is offset, so VLV should be used. - * No explicit sorting. - */ - @Test - public void test174SeachFirst11AccountsOffset2() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(2, 11); - query.setPaging(paging); - - allowDuplicateSearchResults = true; - - // WHEN - SearchResultList> searchResultList = doSearch(query, 11, task, result); - - // THEN - allowDuplicateSearchResults = false; - - // TODO: Why 2? Why not 1? - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * There is offset, so VLV should be used. - * Explicit sorting. - */ - @Test - public void test182Search2AccountsOffset1SortCn() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(1, 2); - paging.setOrdering(getAttributePath(resource, "cn"), OrderDirection.ASCENDING); - query.setPaging(paging); - - SearchResultList> shadows = doSearch(query, 2, task, result); - - assertAccountShadow(shadows.get(0), "CN=Adolf Supperior,CN=Users,DC=ad,DC=evolveum,DC=com"); -// assertAccountShadow(shadows.get(1), "CN=DiscoverySearchMailbox {D919BA05-46A6-415f-80AD-7E09334BB852},CN=Users,DC=ad,DC=evolveum,DC=com"); - - // TODO: Why 2? Why not 1? - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = shadows.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - @Test - public void test200AssignAccountBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - assignAccountToUser(USER_BARBOSSA_OID, getResourceOid(), null, task, result); - - // THEN - then(); - assertSuccess(result); - - long tsEnd = System.currentTimeMillis(); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "title", null); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getShadowModel(shadowOid); - display("Shadow (model)", shadow); - accountBarbossaOid = shadow.getOid(); - Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); - String accountBarbossaIcfUid = (String) identifiers.iterator().next().getRealValue(); - assertNotNull("No identifier in " + shadow, accountBarbossaIcfUid); - - assertEquals("Wrong ICFS UID", - formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), - accountBarbossaIcfUid); - - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); - - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); - - // MID-4624 - ResourceAttribute createTimestampAttribute = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, "createTimeStamp")); - assertNotNull("No createTimestamp in " + shadow, createTimestampAttribute); - XMLGregorianCalendar createTimestamp = createTimestampAttribute.getRealValue(); - long createTimestampMillis = XmlTypeConverter.toMillis(createTimestamp); - // LDAP server may be on a different host. Allow for some clock offset. - TestUtil.assertBetween("Wrong createTimestamp in " + shadow, roundTsDown(tsStart) - 120000, roundTsUp(tsEnd) + 120000, createTimestampMillis); - - assertObjectCategory(shadow, OBJECT_CATEGORY_PERSON); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test210ModifyAccountBarbossaTitle() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta delta = prismContext.deltaFactory().object() - .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); - QName attrQName = new QName(MidPointConstants.NS_RI, ATTRIBUTE_TITLE_NAME); - ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); - PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( - ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, "Captain"); - delta.addModification(attrDelta); - - // WHEN - when(); - executeChanges(delta, null, task, result); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_TITLE_NAME, "Captain"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test212ModifyAccountBarbossaShowInAdvancedViewOnlyTrue() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta delta = prismContext.deltaFactory().object() - .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); - QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); - ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); - PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( - ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); - delta.addModification(attrDelta); - - // WHEN - when(); - executeChanges(delta, null, task, result); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "showInAdvancedViewOnly", "TRUE"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - assertLdapConnectorInstances(2); - } - - /** - * Modify USER, test boolean value mapping. - */ - @Test - public void test213ModifyUserBarbossaShowInAdvancedViewOnlyFalse() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta delta = prismContext.deltaFactory().object() - .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); - QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); - ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); - PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( - ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); - delta.addModification(attrDelta); - - // WHEN - when(); - modifyUserReplace(USER_BARBOSSA_OID, ItemPath.create(UserType.F_EXTENSION, EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME), - task, result, Boolean.FALSE); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "showInAdvancedViewOnly", "FALSE"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - assertLdapConnectorInstances(2); - } - - /** - * Just normal modification of proxyAddress, directly on the account. - * As proxyAddress is multivalue, this is ADD and not REPLACE. This is what GUI would do. - * No previous value for proxyAddress is set in the AD account. - * MID-5330 - */ - @Test - public void test214ModifyAccountBarbossaProxyAddressesSimple() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta delta = prismContext.deltaFactory().object() - .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); - QName attrQName = new QName(MidPointConstants.NS_RI, ATTRIBUTE_PROXY_ADDRESSES_NAME); - ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); - assertNotNull("No definition for attribute " + attrQName, attrDef); - PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationAddProperty( - ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, PROXY_ADDRES_ADDR_UPCASE); - delta.addModification(attrDelta); - - // WHEN - when(); - executeChanges(delta, null, task, result); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_PROXY_ADDRESSES_NAME, PROXY_ADDRES_ADDR_UPCASE); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - -// assertLdapConnectorInstances(2); - } - - /** - * MID-4385 - */ - @Test - public void test216ModifyAccountBarbossaUserParameters() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta delta = prismContext.deltaFactory().object() - .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); - QName attrQName = new QName(MidPointConstants.NS_RI, ATTRIBUTE_USER_PARAMETERS_NAME); - ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); - assertNotNull("No definition for attribute " + attrQName, attrDef); - PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( - ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, VERY_STRANGE_PARAMETER); - delta.addModification(attrDelta); - - // WHEN - when(); - executeChanges(delta, null, task, result); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_USER_PARAMETERS_NAME, VERY_STRANGE_PARAMETER); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - assertModelShadow(shadowOid) - .attributes() - .attribute(ATTRIBUTE_USER_PARAMETERS_NAME) - .assertRealValues(VERY_STRANGE_PARAMETER); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test220ModifyUserBarbossaPasswordSelfServicePassword1() throws Exception { - testModifyUserBarbossaPasswordSelfServiceSuccess( - USER_BARBOSSA_PASSWORD, USER_BARBOSSA_PASSWORD_AD_1); - } - - /** - * Try to set the same password again. If this is "admin mode" (no runAs capability) - * the such change should be successful. In "selfservice mode" (runAs capability - in subclass) - * this change should fail. - */ - @Test - public void test222ModifyUserBarbossaPasswordSelfServicePassword1Again() throws Exception { - testModifyUserBarbossaPasswordSelfServiceSuccess( - USER_BARBOSSA_PASSWORD_AD_1, USER_BARBOSSA_PASSWORD_AD_1); - } - - /** - * Change to different password. This should go well for both admin and self-service. - * MID-5242 - */ - @Test - public void test224ModifyUserBarbossaPasswordSelfServicePassword2() throws Exception { - testModifyUserBarbossaPasswordSelfServiceSuccess( - USER_BARBOSSA_PASSWORD_AD_1, USER_BARBOSSA_PASSWORD_AD_2); - } - - /** - * Change password back to the first password. This password was used before. - * In admin mode this should go well. Admin can set password to anything. - * But in self-service mode (in subclass) this should fail due to password history check. - */ - @Test - public void test226ModifyUserBarbossaPasswordSelfServicePassword1AgainAgain() throws Exception { - testModifyUserBarbossaPasswordSelfServiceSuccess( - USER_BARBOSSA_PASSWORD_AD_2, USER_BARBOSSA_PASSWORD_AD_1); - } - - protected void testModifyUserBarbossaPasswordSelfServiceSuccess(String oldPassword, String newPassword) throws Exception { - // GIVEN - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, oldPassword); - - login(USER_BARBOSSA_USERNAME); - - Task task = getTestTask(); - task.setChannel(SchemaConstants.CHANNEL_GUI_SELF_SERVICE_URI); - OperationResult result = task.getResult(); - - ObjectDelta objectDelta = createOldNewPasswordDelta(USER_BARBOSSA_OID, - oldPassword, newPassword); - - // WHEN - when(); - executeChanges(objectDelta, null, task, result); - - // THEN - then(); - login(USER_ADMINISTRATOR_USERNAME); - assertSuccess(result); - - assertBarbossaEnabled(newPassword); - - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, newPassword); - - assertLdapConnectorInstances(2); - } - - protected void testModifyUserBarbossaPasswordSelfServiceFailure( - String oldPassword, String newPassword) throws Exception { - // GIVEN - login(USER_BARBOSSA_USERNAME); - - Task task = getTestTask(); - task.setChannel(SchemaConstants.CHANNEL_GUI_SELF_SERVICE_URI); - OperationResult result = task.getResult(); - - ObjectDelta objectDelta = createOldNewPasswordDelta(USER_BARBOSSA_OID, - oldPassword, newPassword); - - // WHEN - when(); - executeChanges(objectDelta, null, task, result); - - // THEN - then(); - login(USER_ADMINISTRATOR_USERNAME); - assertPartialError(result); - - assertBarbossaEnabled(newPassword); - assertUserAfter(USER_BARBOSSA_OID) - .assertPassword(newPassword); - - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, oldPassword); - - assertLdapConnectorInstances(2); - } - - @Test - public void test230DisableUserBarbossa() throws Exception { - // precondition - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_AD_1); - - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyUserReplace(USER_BARBOSSA_OID, - SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - task, result, ActivationStatusType.DISABLED); - - // THEN - then(); - assertSuccess(result); - - assertBarbossaDisabled(USER_BARBOSSA_PASSWORD_AD_1); - } - - /** - * MID-4041 - */ - @Test - public void test232ReconcileBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - reconcileUser(USER_BARBOSSA_OID, task, result); - - // THEN - then(); - assertSuccess(result); - - assertBarbossaDisabled(USER_BARBOSSA_PASSWORD_AD_1); - } - - /** - * MID-4041 - */ - @Test - public void test236EnableUserBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyUserReplace(USER_BARBOSSA_OID, - SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - task, result, ActivationStatusType.ENABLED); - - // THEN - then(); - assertSuccess(result); - - assertBarbossaEnabled(USER_BARBOSSA_PASSWORD_AD_1); - - assertLdapConnectorInstances(2); - } - - /** - * MID-4041 - */ - @Test - public void test237ReconcileBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - reconcileUser(USER_BARBOSSA_OID, task, result); - - // THEN - then(); - assertSuccess(result); - - assertBarbossaEnabled(USER_BARBOSSA_PASSWORD_AD_1); - - assertLdapConnectorInstances(2); - } - - /** - * MID-4041 - */ - @Test - public void test238DisableUserBarbossaRawAndReconcile() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - modifyUserReplace(USER_BARBOSSA_OID, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - ModelExecuteOptions.createRaw(), task, result, ActivationStatusType.DISABLED); - - // WHEN - when(); - reconcileUser(USER_BARBOSSA_OID, task, result); - - // THEN - then(); - assertSuccess(result); - - assertBarbossaDisabled(USER_BARBOSSA_PASSWORD_AD_1); - - assertLdapConnectorInstances(2); - } - - /** - * MID-4041 - */ - @Test - public void test239EnableUserBarbossaRawAndReconcile() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - modifyUserReplace(USER_BARBOSSA_OID, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - ModelExecuteOptions.createRaw(), task, result, ActivationStatusType.ENABLED); - - // WHEN - when(); - reconcileUser(USER_BARBOSSA_OID, task, result); - - // THEN - then(); - assertSuccess(result); - - assertBarbossaEnabled(USER_BARBOSSA_PASSWORD_AD_1); - - assertLdapConnectorInstances(2); - } - - protected PrismObject assertBarbossaEnabled(String ldapPassword) throws Exception { - PrismObject user = getUser(USER_BARBOSSA_OID); - assertAdministrativeStatus(user, ActivationStatusType.ENABLED); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "title", "Captain"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - assertAttribute(entry, ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME, "FALSE"); - - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - assertAccountEnabled(shadow); - - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, ldapPassword); - - return user; - } - - private void assertBarbossaDisabled(String password) throws Exception { - assertLdapConnectorInstances(2); - - PrismObject user = getUser(USER_BARBOSSA_OID); - assertAdministrativeStatus(user, ActivationStatusType.DISABLED); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - displayValue("disabled Barbossa entry", entry); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); - - assertAttribute(entry, ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME, "TRUE"); - - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - assertAccountDisabled(shadow); - - try { - assertLdapPassword(null, entry, password); - AssertJUnit.fail("Password authentication works, but it should fail"); - } catch (SecurityException e) { - // this is expected - } - - assertLdapConnectorInstances(2); - } - - /** - * This should create account with a group. And the account should be disabled. - */ - @Test - public void test250AssignGuybrushPirates() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - -// ProtectedStringType userPasswordPs = new ProtectedStringType(); -// userPasswordPs.setClearValue(USER_GUYBRUSH_PASSWORD_333); -// modifyUserReplace(USER_GUYBRUSH_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); - modifyUserReplace(USER_GUYBRUSH_OID, - SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - task, result, ActivationStatusType.DISABLED); - - // WHEN - when(); - assignRole(USER_GUYBRUSH_OID, ROLE_PIRATES_OID, task, result); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - displayValue("Entry", entry); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); - - assertLdapGroupMember(entry, GROUP_PIRATES_NAME); - - PrismObject user = getUser(USER_GUYBRUSH_OID); - assertAdministrativeStatus(user, ActivationStatusType.DISABLED); - String shadowOid = getSingleLinkOid(user); - - PrismObject shadow = getObject(ShadowType.class, shadowOid); - IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); - assertAccountDisabled(shadow); - -// try { -// assertLdapPassword(null, entry, USER_GUYBRUSH_PASSWORD_333); -// AssertJUnit.fail("Password authentication works, but it should fail"); -// } catch (SecurityException e) { -// // this is expected, account is disabled -// } - - assertLdapConnectorInstances(2); - } - - @Test - public void test255ModifyUserGuybrushPassword() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ProtectedStringType userPasswordPs = new ProtectedStringType(); - userPasswordPs.setClearValue(USER_GUYBRUSH_PASSWORD_123); - - // WHEN - when(); - modifyUserReplace(USER_GUYBRUSH_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - displayValue("Guybrush entry after", entry); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); - - try { - assertLdapPassword(null, entry, USER_GUYBRUSH_PASSWORD_123); - AssertJUnit.fail("Password authentication works, but it should fail"); - } catch (SecurityException e) { - // this is expected, account is disabled - } - -// assertLdapConnectorInstances(2); - } - - @Test - public void test260EnableGyubrush() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyUserReplace(USER_GUYBRUSH_OID, - SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - task, result, ActivationStatusType.ENABLED); - - // THEN - then(); - assertSuccess(result); - - PrismObject user = getUser(USER_GUYBRUSH_OID); - assertAdministrativeStatus(user, ActivationStatusType.ENABLED); - - Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - assertAccountEnabled(shadow); - - assertLdapPassword(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME, "wanna.be.a.123"); - - assertLdapConnectorInstances(2); - } - - /** - * Try to create an account without password. This should end up with an error. - * A reasonable error. - * MID-4046 - */ - @Test - public void test270AssignAccountToEmptyhead() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - PrismObject userBefore = createUser(USER_EMPTYHEAD_NAME, USER_EMPTYHEAD_NAME, true); - display("User before", userBefore); - addObject(userBefore); - String userEmptyheadOid = userBefore.getOid(); - - // WHEN - when(); - assignAccountToUser(userEmptyheadOid, getResourceOid(), null, task, result); - - // THEN - then(); - assertPartialError(result); - - assertMessageContains(result.getMessage(), "does not meet the length, complexity, or history requirement"); - - assertLdapConnectorInstances(2); - } - - /** - * Just make random test connection between the tests. Make sure that the - * test does not break anything. If it does the next tests will simply fail. - */ - @Test - public void test295TestConnection() throws Exception { - // GIVEN - Task task = getTestTask(); - - // WHEN - when(); - OperationResult testResult = modelService.testResource(getResourceOid(), task); - - // THEN - then(); - display("Test connection result", testResult); - TestUtil.assertSuccess("Test connection result", testResult); - - // Test is disposing connector facade and the entire connector pool. - // Therefore we are back at 1 instance. - assertLdapConnectorInstances(1); - } - - @Test - public void test300AssignBarbossaPirates() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - assignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - displayValue("Entry", entry); - assertAttribute(entry, "title", "Captain"); - - assertLdapGroupMember(entry, GROUP_PIRATES_NAME); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - PrismObject shadow = getObject(ShadowType.class, shadowOid); - IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); - - assertLdapConnectorInstances(1); - } - - @Test - public void test390ModifyUserBarbossaRename() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta objectDelta = createModifyUserReplaceDelta(USER_BARBOSSA_OID, UserType.F_NAME, - PrismTestUtil.createPolyString(USER_CPTBARBOSSA_USERNAME)); - objectDelta.addModificationReplaceProperty(UserType.F_FULL_NAME, - PrismTestUtil.createPolyString(USER_CPTBARBOSSA_FULL_NAME)); - Collection> deltas = MiscSchemaUtil.createCollection(objectDelta); - - // WHEN - when(); - modelService.executeChanges(deltas, null, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); - assertAttribute(entry, "title", "Captain"); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - display("Shadow after rename (model)", shadow); - - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, shadowOid, null, result); - display("Shadow after rename (repo)", repoShadow); - - assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - -// assertLdapConnectorInstances(2); - } - - // TODO: create account with a group membership - - @Test - public void test395UnAssignBarbossaPirates() throws Exception { - // TODO: do this on another account. There is a bad interference with rename. - - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - unassignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); - displayValue("Entry", entry); - assertAttribute(entry, "title", "Captain"); - - assertLdapNoGroupMember(entry, GROUP_PIRATES_NAME); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - PrismObject shadow = getObject(ShadowType.class, shadowOid); - IntegrationTestTools.assertNoAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test399UnAssignAccountBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - unassignAccountFromUser(USER_BARBOSSA_OID, getResourceOid(), null, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertNoLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); - - PrismObject user = getUser(USER_BARBOSSA_OID); - assertNoLinkedAccount(user); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test500AddOrgMeleeIsland() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - PrismObject org = instantiateObject(OrgType.class); - OrgType orgType = org.asObjectable(); - orgType.setName(new PolyStringType(GROUP_MELEE_ISLAND_NAME)); - AssignmentType metaroleAssignment = new AssignmentType(); - ObjectReferenceType metaroleRef = new ObjectReferenceType(); - metaroleRef.setOid(ROLE_META_ORG_OID); - metaroleRef.setType(RoleType.COMPLEX_TYPE); - metaroleAssignment.setTargetRef(metaroleRef); - orgType.getAssignment().add(metaroleAssignment); - - // WHEN - when(); - addObject(org, task, result); - - // THEN - then(); - assertSuccess(result); - - orgMeleeIslandOid = org.getOid(); - assertLdapGroup(GROUP_MELEE_ISLAND_NAME); - assertLdapOrg(GROUP_MELEE_ISLAND_NAME); - - org = getObject(OrgType.class, orgMeleeIslandOid); - groupMeleeIslandOid = getLinkRefOid(org, getResourceOid(), ShadowKindType.ENTITLEMENT, INTENT_GROUP); - ouMeleeIslandOid = getLinkRefOid(org, getResourceOid(), ShadowKindType.GENERIC, INTENT_OU_TOP); - assertLinks(org, 2); - - PrismObject shadowGroup = getShadowModel(groupMeleeIslandOid); - display("Shadow: group (model)", shadowGroup); - - PrismObject shadowOu = getShadowModel(ouMeleeIslandOid); - display("Shadow: ou (model)", shadowOu); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test510AssignGuybrushMeleeIsland() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - assignOrg(USER_GUYBRUSH_OID, orgMeleeIslandOid, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - - PrismObject user = getUser(USER_GUYBRUSH_OID); - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getShadowModel(shadowOid); - display("Shadow (model)", shadow); - - assertLdapGroupMember(entry, GROUP_MELEE_ISLAND_NAME); - - IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupMeleeIslandOid); - -// assertLdapConnectorInstances(2); - } - - /** - * Create role under the Melee Island org. This creates group in the orgstruct. - */ - @Test - public void test515AddOrgGroupMeleeIslandPirates() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - PrismObject role = instantiateObject(RoleType.class); - RoleType roleType = role.asObjectable(); - roleType.setName(new PolyStringType(GROUP_MELEE_ISLAND_PIRATES_NAME)); - - AssignmentType metaroleAssignment = new AssignmentType(); - ObjectReferenceType metaroleRef = new ObjectReferenceType(); - metaroleRef.setOid(ROLE_META_ORG_GROUP_OID); - metaroleRef.setType(RoleType.COMPLEX_TYPE); - metaroleAssignment.setTargetRef(metaroleRef); - roleType.getAssignment().add(metaroleAssignment); - - AssignmentType orgAssignment = new AssignmentType(); - ObjectReferenceType orgRef = new ObjectReferenceType(); - orgRef.setOid(orgMeleeIslandOid); - orgRef.setType(OrgType.COMPLEX_TYPE); - orgAssignment.setTargetRef(orgRef); - roleType.getAssignment().add(orgAssignment); - - // WHEN - when(); - addObject(role, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - roleMeleeIslandPiratesOid = role.getOid(); - // TODO: assert LDAP object - - assertLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); - - PrismObject roleAfter = getObject(RoleType.class, roleMeleeIslandPiratesOid); - display("Role after", roleAfter); - groupMeleeIslandPiratesOid = getSingleLinkOid(roleAfter); - PrismObject shadow = getShadowModel(groupMeleeIslandPiratesOid); - display("Shadow (model)", shadow); - } - - /** - * Rename org unit. MidPoint should rename OU and ordinary group. - * AD will rename the group in the orgstruct automatically. We need to - * make sure that we can still access that group. - */ - @Test - public void test520RenameMeleeIsland() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - renameObject(OrgType.class, orgMeleeIslandOid, GROUP_MELEE_ISLAND_ALT_NAME, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - PrismObject orgAfter = getObject(OrgType.class, orgMeleeIslandOid); - groupMeleeIslandOid = getLinkRefOid(orgAfter, getResourceOid(), ShadowKindType.ENTITLEMENT, INTENT_GROUP); - ouMeleeIslandOid = getLinkRefOid(orgAfter, getResourceOid(), ShadowKindType.GENERIC, INTENT_OU_TOP); - assertLinks(orgAfter, 2); - - PrismObject shadowGroup = getShadowModel(groupMeleeIslandOid); - display("Shadow: group (model)", shadowGroup); - - PrismObject shadowOu = getShadowModel(ouMeleeIslandOid); - display("Shadow: ou (model)", shadowOu); - - assertLdapGroup(GROUP_MELEE_ISLAND_ALT_NAME); - assertNoLdapGroup(GROUP_MELEE_ISLAND_NAME); - - assertLdapOrg(GROUP_MELEE_ISLAND_ALT_NAME); - assertNoLdapOrg(GROUP_MELEE_ISLAND_NAME); - - assertLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME); - assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); - - Entry entryGuybrush = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - - PrismObject user = getUser(USER_GUYBRUSH_OID); - String shadowAccountOid = getSingleLinkOid(user); - PrismObject shadowAccount = getShadowModel(shadowAccountOid); - display("Shadow: account (model)", shadowAccount); - - assertLdapGroupMember(entryGuybrush, GROUP_MELEE_ISLAND_ALT_NAME); - - IntegrationTestTools.assertAssociation(shadowAccount, getAssociationGroupQName(), groupMeleeIslandOid); - -// assertLdapConnectorInstances(2); - } - - /** - * AD renamed the pirate groups by itself. MidPoint does not know about it. - * The GUID that is stored in the shadow is still OK. But the DN is now out - * of date. Try to update the group. Make sure it works. - * It is expected that the GUI will be used as a primary identifier. - * Note: just reading the group will NOT work. MidPoint is too smart - * for that. It will transparently fix the situation. - */ - @Test - public void test522ModifyMeleeIslandPirates() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyObjectReplaceProperty(ShadowType.class, groupMeleeIslandPiratesOid, - ItemPath.create(ShadowType.F_ATTRIBUTES, new QName(MidPointConstants.NS_RI, "description")), - task, result, GROUP_MELEE_ISLAND_PIRATES_DESCRIPTION); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entryOrgGroup = assertLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME); - assertAttribute(entryOrgGroup, "description", GROUP_MELEE_ISLAND_PIRATES_DESCRIPTION); - - assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test524GetMeleeIslandPirates() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - PrismObject shadow = modelService.getObject(ShadowType.class, groupMeleeIslandPiratesOid, null, task, result); - - // THEN - then(); - assertSuccess(result); - - display("Shadow after", shadow); - assertNotNull(shadow); - - assertLdapGroup(GROUP_MELEE_ISLAND_ALT_NAME); - assertNoLdapGroup(GROUP_MELEE_ISLAND_NAME); - assertLdapOrg(GROUP_MELEE_ISLAND_ALT_NAME); - assertNoLdapOrg(GROUP_MELEE_ISLAND_NAME); - Entry entryOrgGroup = assertLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME); - displayValue("Melee org", entryOrgGroup); - assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); - } - - @Test - public void test595DeleteOrgGroupMeleeIslandPirates() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - deleteObject(RoleType.class, roleMeleeIslandPiratesOid, task, result); - - // THEN - then(); - assertSuccess(result); - - assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME); - assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); - - assertNoObject(ShadowType.class, groupMeleeIslandPiratesOid); - -// assertLdapConnectorInstances(2); - } - - /** - * We create "underMelee" org that gets into the way of the delete. - * Melee cannot be deleted in an ordinary way. "tree delete" control must - * be used. This is configured in the connector config. - *

- * MID-5935 - */ - @Test - public void test599DeleteOrgMeleeIsland() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - createUnderMeleeEntry(); - - // WHEN - when(); - deleteObject(OrgType.class, orgMeleeIslandOid, task, result); - - // THEN - then(); - assertSuccess(result); - - assertNoLdapGroup(GROUP_MELEE_ISLAND_NAME); - assertNoLdapGroup(GROUP_MELEE_ISLAND_ALT_NAME); - assertNoLdapOrg(GROUP_MELEE_ISLAND_NAME); - assertNoLdapOrg(GROUP_MELEE_ISLAND_ALT_NAME); - - assertNoObject(ShadowType.class, groupMeleeIslandOid); - assertNoObject(ShadowType.class, ouMeleeIslandOid); - -// assertLdapConnectorInstances(2); - } - - protected void createUnderMeleeEntry() throws LdapException, IOException { - // This OU just gets into the way of the delete. - Entry entry = new DefaultEntry("ou=underMelee," + toOrgDn(GROUP_MELEE_ISLAND_ALT_NAME), - "objectclass", "organizationalUnit", - "ou", "underMelee"); - displayValue("underMelee org", entry); - addLdapEntry(entry); - } - - @Test - public void test600AssignAccountSubman() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - assignRole(USER_SUBMAN_OID, ROLE_SUBMISSIVE_OID, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - long tsEnd = System.currentTimeMillis(); - - Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); - displayValue("Sub entry", entry); - assertAttribute(entry, "title", null); - - PrismObject userAfter = getUser(USER_SUBMAN_OID); - String shadowOid = getSingleLinkOid(userAfter); - PrismObject shadow = getShadowModel(shadowOid); - display("Shadow (model)", shadow); - accountSubmanOid = shadow.getOid(); - Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); - String accountBarbossaIcfUid = (String) identifiers.iterator().next().getRealValue(); - assertNotNull("No identifier in " + shadow, accountBarbossaIcfUid); - - assertEquals("Wrong ICFS UID", - formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), - accountBarbossaIcfUid); - - assertLdapPassword(getSubLdapConnectionConfig(), USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME, USER_SUBMAN_PASSWORD); - - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - // MID-4624 - ResourceAttribute createTimestampAttribute = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, "createTimeStamp")); - assertNotNull("No createTimestamp in " + shadow, createTimestampAttribute); - XMLGregorianCalendar createTimestamp = createTimestampAttribute.getRealValue(); - long createTimestampMillis = XmlTypeConverter.toMillis(createTimestamp); - // LDAP server may be on a different host. Allow for some clock offset. - TestUtil.assertBetween("Wrong createTimestamp in " + shadow, roundTsDown(tsStart) - 120000, roundTsUp(tsEnd) + 120000, createTimestampMillis); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test610ModifyUserSubmanTitle() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyUserReplace(USER_SUBMAN_OID, UserType.F_TITLE, task, result, - createPolyString("Underdog")); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); - displayValue("Sub entry", entry); - assertAttribute(entry, "title", "Underdog"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - PrismObject user = getUser(USER_SUBMAN_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountSubmanOid, shadowOid); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test620ModifyUserSubmanPassword() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ProtectedStringType userPasswordPs = new ProtectedStringType(); - userPasswordPs.setClearValue("SuB.321"); - - // WHEN - when(); - modifyUserReplace(USER_SUBMAN_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); - assertAttribute(entry, "title", "Underdog"); - assertLdapPassword(getSubLdapConnectionConfig(), USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME, "SuB.321"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - PrismObject user = getUser(USER_SUBMAN_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountSubmanOid, shadowOid); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test630DisableUserSubman() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyUserReplace(USER_SUBMAN_OID, - SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - task, result, ActivationStatusType.DISABLED); - - // THEN - then(); - assertSuccess(result); - -// assertLdapConnectorInstances(2); - - PrismObject user = getUser(USER_SUBMAN_OID); - assertAdministrativeStatus(user, ActivationStatusType.DISABLED); - - Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); - - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - assertAccountDisabled(shadow); - - try { - assertLdapPassword(getSubLdapConnectionConfig(), USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME, "SuB.321"); - AssertJUnit.fail("Password authentication works, but it should fail"); - } catch (SecurityException e) { - // this is expected - } - -// assertLdapConnectorInstances(2); - } - - @Test - public void test639EnableUserSubman() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyUserReplace(USER_SUBMAN_OID, - SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - task, result, ActivationStatusType.ENABLED); - - // THEN - then(); - assertSuccess(result); - - PrismObject user = getUser(USER_SUBMAN_OID); - assertAdministrativeStatus(user, ActivationStatusType.ENABLED); - - Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - assertAccountEnabled(shadow); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test690ModifyUserSubmanRename() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta objectDelta = createModifyUserReplaceDelta(USER_SUBMAN_OID, UserType.F_NAME, - createPolyString(USER_SUBDOG_USERNAME)); - objectDelta.addModificationReplaceProperty(UserType.F_FULL_NAME, - createPolyString(USER_SUBDOG_FULL_NAME)); - - // WHEN - when(); - executeChanges(objectDelta, null, task, result); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapSubAccount(USER_SUBDOG_USERNAME, USER_SUBDOG_FULL_NAME); - assertAttribute(entry, "title", "Underdog"); - - PrismObject user = getUser(USER_SUBMAN_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountSubmanOid, shadowOid); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - display("Shadow after rename (model)", shadow); - - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, shadowOid, null, result); - display("Shadow after rename (repo)", repoShadow); - - assertNoLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test699UnAssignAccountSubdog() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - unassignRole(USER_SUBMAN_OID, ROLE_SUBMISSIVE_OID, task, result); - - // THEN - then(); - assertSuccess(result); - - assertNoLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); - assertNoLdapSubAccount(USER_SUBDOG_USERNAME, USER_SUBDOG_FULL_NAME); - - PrismObject user = getUser(USER_SUBMAN_OID); - assertNoLinkedAccount(user); - -// assertLdapConnectorInstances(2); - } - - /** - * Create account and modify it in a very quick succession. - * This test is designed to check if we can live with a long - * global catalog update delay. - * MID-2926 - */ - @Test - public void test700AssignAccountSubmarineAndModify() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - assignRole(USER_SUBMARINE_OID, ROLE_SUBMISSIVE_OID, task, result); - - modifyUserReplace(USER_SUBMARINE_OID, UserType.F_TITLE, task, result, - PrismTestUtil.createPolyString("Underseadog")); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapSubAccount(USER_SUBMARINE_USERNAME, USER_SUBMARINE_FULL_NAME); - displayValue("Sub entry", entry); - assertAttribute(entry, "title", "Underseadog"); - - PrismObject userAfter = getUser(USER_SUBMARINE_OID); - String shadowOid = getSingleLinkOid(userAfter); - PrismObject shadow = getShadowModel(shadowOid); - display("Shadow (model)", shadow); - accountSubmarineOid = shadow.getOid(); - Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); - String accountIcfUid = (String) identifiers.iterator().next().getRealValue(); - assertNotNull("No identifier in " + shadow, accountIcfUid); - - assertEquals("Wrong ICFS UID", - formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), - accountIcfUid); - - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - } - - @Test - public void test809UnAssignAccountSubmarine() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - unassignRole(USER_SUBMARINE_OID, ROLE_SUBMISSIVE_OID, task, result); - - // THEN - then(); - assertSuccess(result); - - assertNoLdapSubAccount(USER_SUBMARINE_USERNAME, USER_SUBMARINE_FULL_NAME); - - PrismObject user = getUser(USER_SUBMARINE_OID); - assertNoLinkedAccount(user); - } - - @Test - public void test850ReconcileAccounts() throws Exception { - // GIVEN - assertUsers(6); - - // WHEN - when(); - addTask(getReconciliationTaskFile()); - - waitForTaskFinish(getReconciliationTaskOid(), true); - - // THEN - then(); - - assertUsers(15); - // TODO - -// assertLdapConnectorInstances(2); - } - - // DISABLED because we do not know how to properly configure sync privileges in a AD forrest. - // More experiments are needed, but only after we migrate our old AD servers. - @Test(enabled=false) - public void test900ImportSyncTask() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - addObject(getSyncTaskFile(), task, result); - - // THEN - then(); - assertSuccess(result); - - waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); - - long tsEnd = System.currentTimeMillis(); - - assertStepSyncToken(getSyncTaskOid(), 0, tsStart, tsEnd); - } - - // DISABLED because we do not know how to properly configure sync privileges in a AD forrest. - // More experiments are needed, but only after we migrate our old AD servers. - @Test(enabled=false) - public void test901SyncAddAccountHt() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - addLdapAccount(ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN); - waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); - - // THEN - then(); - assertSuccess(result); - - long tsEnd = System.currentTimeMillis(); - - displayUsers(); - - PrismObject user = findUserByUsername(ACCOUNT_HT_UID); - assertNotNull("No user " + ACCOUNT_HT_UID + " created", user); - assertUser(user, user.getOid(), ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN); - - assertStepSyncToken(getSyncTaskOid(), 1, tsStart, tsEnd); - } - - protected void assertStepSyncToken(String syncTaskOid, int step, long tsStart, long tsEnd) - throws ObjectNotFoundException, SchemaException { - OperationResult result = createOperationResult("assertStepSyncToken"); - Task task = taskManager.getTaskPlain(syncTaskOid, result); - PrismProperty syncTokenProperty = task.getExtensionPropertyOrClone(SchemaConstants.SYNC_TOKEN); - assertNotNull("No sync token", syncTokenProperty); - assertNotNull("No sync token value", syncTokenProperty.getRealValue()); - assertNotNull("Empty sync token value", StringUtils.isBlank(syncTokenProperty.getRealValue())); - assertSuccess(result); - } - - @Override - protected void assertAccountShadow(PrismObject shadow, String dn) throws SchemaException { - super.assertAccountShadow(shadow, dn); - ResourceAttribute primaryIdAttr = ShadowUtil.getAttribute(shadow, getPrimaryIdentifierAttributeQName()); - assertNotNull("No primary identifier (" + getPrimaryIdentifierAttributeQName() + " in " + shadow, primaryIdAttr); - String primaryId = primaryIdAttr.getRealValue(); - assertTrue("Unexpected chars in primary ID: '" + primaryId + "'", primaryId.matches("[a-z0-9\\-]+")); - - ResourceAttribute objectSidAttr = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, ATTRIBUTE_OBJECT_SID_NAME)); - assertNotNull("No SID in " + shadow, objectSidAttr); - display("SID of " + dn + ": " + objectSidAttr); - } - - protected void assertSid(PrismObject shadow, String expectedSid) { - ResourceAttribute objectSidAttr = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, ATTRIBUTE_OBJECT_SID_NAME)); - assertNotNull("No SID in " + shadow, objectSidAttr); - display("SID of " + shadow + ": " + objectSidAttr); - assertEquals("Wrong SID in " + shadow, expectedSid, objectSidAttr.getRealValue()); - } - - private void assertObjectCategory(PrismObject shadow, String expectedObjectCategory) { - ResourceAttribute objectCategoryAttr = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, ATTRIBUTE_OBJECT_CATEGORY_NAME)); - assertNotNull("No objectCategory in " + shadow, objectCategoryAttr); - display("objectCategory of " + shadow + ": " + objectCategoryAttr); - assertEquals("Wrong objectCategory in " + shadow, expectedObjectCategory, objectCategoryAttr.getRealValue()); - } - - @Override - protected Entry assertLdapAccount(String samAccountName, String cn) throws LdapException, IOException, CursorException { - Entry entry = searchLdapAccount("(cn=" + cn + ")"); - assertAttribute(entry, "cn", cn); - assertAttribute(entry, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName); - return entry; - } - - protected Entry assertLdapSubAccount(String samAccountName, String cn) throws LdapException, IOException, CursorException { - Entry entry = searchLdapAccount(getSubLdapConnectionConfig(), "(cn=" + cn + ")"); - assertAttribute(entry, "cn", cn); - assertAttribute(entry, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName); - return entry; - } - - @Override - protected void assertNoLdapAccount(String uid) { - throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); - } - - protected void assertNoLdapAccount(String uid, String cn) throws LdapException, IOException, CursorException { - assertNoLdapAccount(null, uid, cn); - } - - protected void assertNoLdapSubAccount(String uid, String cn) throws LdapException, IOException, CursorException { - assertNoLdapAccount(getSubLdapConnectionConfig(), uid, cn); - } - - protected void assertNoLdapAccount(UserLdapConnectionConfig config, String uid, String cn) throws LdapException, IOException, CursorException { - LdapNetworkConnection connection = ldapConnect(config); - List entriesCn = ldapSearch(config, connection, "(cn=" + cn + ")"); - List entriesSamAccountName = ldapSearch(config, connection, "(sAMAccountName=" + uid + ")"); - ldapDisconnect(connection); - - assertEquals("Unexpected number of entries for cn=" + cn + ": " + entriesCn, 0, entriesCn.size()); - assertEquals("Unexpected number of entries for sAMAccountName=" + uid + ": " + entriesSamAccountName, 0, entriesSamAccountName.size()); - } - - @Override - protected String toAccountDn(String username) { - throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); - } - - @Override - protected String toAccountDn(String username, String fullName) { - return ("CN=" + fullName + "," + getPeopleLdapSuffix()); - } - - protected String toAccountSubDn(String username, String fullName) { - return ("CN=" + fullName + "," + getPeopleLdapSubSuffix()); - } - - @Override - protected Rdn toAccountRdn(String username, String fullName) { - try { - return new Rdn(new Ava("CN", fullName)); - } catch (LdapInvalidDnException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - protected String toOrgDn(String cn) { - return "ou=" + cn + "," + getOrgsLdapSuffix(); - } - - protected String toOrgGroupDn(String groupCn, String orgName) { - return "cn=" + groupCn + "," + toOrgDn(orgName); - } - - protected Entry assertLdapOrg(String orgName) throws LdapException, IOException, CursorException { - String dn = toOrgDn(orgName); - Entry entry = getLdapEntry(dn); - assertNotNull("No entry " + dn, entry); - assertAttribute(entry, "ou", orgName); - return entry; - } - - protected Entry assertNoLdapOrg(String orgName) throws LdapException, IOException, CursorException { - String dn = toOrgDn(orgName); - Entry entry = getLdapEntry(dn); - assertNull("Unexpected org entry " + entry, entry); - return entry; - } - - protected Entry assertLdapOrgGroup(String groupCn, String orgName) throws LdapException, IOException, CursorException { - String dn = toOrgGroupDn(groupCn, orgName); - Entry entry = getLdapEntry(dn); - assertNotNull("No entry " + dn, entry); - assertAttribute(entry, "cn", groupCn); - return entry; - } - - protected Entry assertNoLdapOrgGroup(String groupCn, String orgName) throws LdapException, IOException, CursorException { - String dn = toOrgGroupDn(groupCn, orgName); - Entry entry = getLdapEntry(dn); - assertNull("Unexpected org group entry " + entry, entry); - return entry; - } - - protected void assertLdapPassword(String uid, String fullName, String password) throws LdapException, IOException, CursorException { - assertLdapPassword(null, uid, fullName, password); - } - - protected void assertLdapPassword(UserLdapConnectionConfig config, String uid, String fullName, String password) throws LdapException, IOException, CursorException { - Entry entry = getLdapAccountByCn(config, fullName); - assertLdapPassword(config, entry, password); - } - - protected void assertLdapPassword(String uid, String password) { - throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); - } - - protected ObjectQuery createSamAccountNameQuery(String samAccountName) throws SchemaException { - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter(ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName), - prismContext); - return query; - } - - @Override - protected Entry createAccountEntry(String uid, String cn, String givenName, String sn) throws LdapException { - byte[] password = encodePassword("Secret.123"); - Entry entry = new DefaultEntry(toAccountDn(uid, cn), - "objectclass", getLdapAccountObjectClass(), - ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, uid, - "cn", cn, - "givenName", givenName, - "sn", sn, - ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512", - ATTRIBUTE_UNICODE_PWD_NAME, password); - return entry; - } - - private byte[] encodePassword(String password) { - String quotedPassword = "\"" + password + "\""; - try { - return quotedPassword.getBytes("UTF-16LE"); - } catch (UnsupportedEncodingException e) { - throw new SystemException(e.getMessage(), e); - } - } - - public void assertAttribute(PrismObject shadow, String attrName, T... expectedValues) { - assertAttribute(shadow, new QName(getResourceNamespace(), attrName), expectedValues); - } - - public void assertAttribute(PrismObject shadow, QName attrQname, T... expectedValues) { - List actualValues = ShadowUtil.getAttributeValues(shadow, attrQname); - PrismAsserts.assertSets("attribute " + attrQname + " in " + shadow, actualValues, expectedValues); - } - - protected abstract void assertAccountDisabled(PrismObject shadow); - - protected abstract void assertAccountEnabled(PrismObject shadow); - -} +/* + * Copyright (c) 2015-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.testing.conntest.ad; + +import static org.testng.AssertJUnit.*; + +import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_CREDENTIALS_PASSWORD_VALUE; + +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Collection; +import java.util.List; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.prism.PrismProperty; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; + +import org.apache.commons.lang3.StringUtils; +import org.apache.directory.api.ldap.model.cursor.CursorException; +import org.apache.directory.api.ldap.model.entry.DefaultEntry; +import org.apache.directory.api.ldap.model.entry.Entry; +import org.apache.directory.api.ldap.model.exception.LdapException; +import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; +import org.apache.directory.api.ldap.model.name.Ava; +import org.apache.directory.api.ldap.model.name.Rdn; +import org.apache.directory.ldap.client.api.LdapNetworkConnection; +import org.testng.AssertJUnit; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; + +import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; +import com.evolveum.midpoint.model.api.ModelExecuteOptions; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.delta.PropertyDelta; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.ObjectPaging; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.OrderDirection; +import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.prism.util.PrismTestUtil; +import com.evolveum.midpoint.prism.xml.XmlTypeConverter; +import com.evolveum.midpoint.schema.SearchResultList; +import com.evolveum.midpoint.schema.SearchResultMetadata; +import com.evolveum.midpoint.schema.constants.MidPointConstants; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.internals.InternalCounters; +import com.evolveum.midpoint.schema.processor.ResourceAttribute; +import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; +import com.evolveum.midpoint.schema.processor.ResourceSchema; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.MiscSchemaUtil; +import com.evolveum.midpoint.schema.util.ObjectQueryUtil; +import com.evolveum.midpoint.schema.util.ShadowUtil; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.test.IntegrationTestTools; +import com.evolveum.midpoint.test.util.MidPointTestConstants; +import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.testing.conntest.AbstractLdapTest; +import com.evolveum.midpoint.testing.conntest.UserLdapConnectionConfig; +import com.evolveum.midpoint.util.MiscUtil; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.exception.SystemException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; +import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; + +/** + * @author semancik + */ +@Listeners({ com.evolveum.midpoint.tools.testng.AlphabeticalMethodInterceptor.class }) +public abstract class AbstractAdLdapMultidomainTest extends AbstractLdapTest + implements AdTestMixin { + + protected static final File TEST_DIR = new File(MidPointTestConstants.TEST_RESOURCES_DIR, "ad-ldap-multidomain"); + + protected static final File ROLE_PIRATES_FILE = new File(TEST_DIR, "role-pirate.xml"); + protected static final String ROLE_PIRATES_OID = "5dd034e8-41d2-11e5-a123-001e8c717e5b"; + + protected static final File ROLE_SUBMISSIVE_FILE = new File(TEST_DIR, "role-submissive.xml"); + protected static final String ROLE_SUBMISSIVE_OID = "0c0c81b2-d0a1-11e5-b51e-0309a826745e"; + + protected static final File ROLE_META_ORG_FILE = new File(TEST_DIR, "role-meta-org.xml"); + protected static final String ROLE_META_ORG_OID = "f2ad0ace-45d7-11e5-af54-001e8c717e5b"; + + protected static final File ROLE_META_ORG_GROUP_FILE = new File(TEST_DIR, "role-meta-org-group.xml"); + protected static final String ROLE_META_ORG_GROUP_OID = "c5d3294a-0d8e-11e7-bd9d-ff848c2e7e3f"; + + protected static final String ACCOUNT_JACK_SAM_ACCOUNT_NAME = "jack"; + protected static final String ACCOUNT_JACK_SID = "S-1-5-21-3305462238-3617280118-659738602-4878"; + protected static final String ACCOUNT_JACK_FULL_NAME = "Jack Sparrow"; + protected static final String ACCOUNT_JACK_PASSWORD = "qwe.123"; + + protected static final String ACCOUNT_HT_UID = "ht"; + protected static final String ACCOUNT_HT_CN = "Herman Toothrot"; + protected static final String ACCOUNT_HT_GIVENNAME = "Herman"; + protected static final String ACCOUNT_HT_SN = "Toothrot"; + protected static final String ACCOUNT_HT_SN_MODIFIED = "Torquemeda Marley"; + + protected static final String ACCOUNT_HTM_UID = "htm"; + protected static final String ACCOUNT_HTM_CN = "Horatio Torquemada Marley"; + + protected static final String USER_CPTBARBOSSA_FULL_NAME = "Captain Hector Barbossa"; + + private static final String GROUP_PIRATES_NAME = "pirates"; + private static final String GROUP_MELEE_ISLAND_NAME = "Mêlée Island"; + private static final String GROUP_MELEE_ISLAND_ALT_NAME = "Alternative Mêlée Island"; + private static final String GROUP_MELEE_ISLAND_PIRATES_NAME = "Mêlée Island Pirates"; + private static final String GROUP_MELEE_ISLAND_PIRATES_DESCRIPTION = "swashbuckle and loot"; + + protected static final int NUMBER_OF_ACCOUNTS = 18; + private static final String ASSOCIATION_GROUP_NAME = "group"; + + private static final String NS_EXTENSION = "http://whatever.com/my"; + private static final QName EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME = new QName(NS_EXTENSION, "showInAdvancedViewOnly"); + + protected static final File USER_SUBMAN_FILE = new File(TEST_DIR, "user-subman.xml"); + private static final String USER_SUBMAN_OID = "910ac45a-8bd6-11e6-9122-ef88d95095f0"; + private static final String USER_SUBMAN_USERNAME = "subman"; + private static final String USER_SUBMAN_GIVEN_NAME = "Sub"; + private static final String USER_SUBMAN_FAMILY_NAME = "Man"; + private static final String USER_SUBMAN_FULL_NAME = "Sub Man"; + private static final String USER_SUBMAN_PASSWORD = "sub.123"; + + private static final String USER_SUBDOG_USERNAME = "subdog"; + private static final String USER_SUBDOG_GIVEN_NAME = "Sub"; + private static final String USER_SUBDOG_FAMILY_NAME = "Dog"; + private static final String USER_SUBDOG_FULL_NAME = "Sub Dog"; + + protected static final File USER_SUBMARINE_FILE = new File(TEST_DIR, "user-submarine.xml"); + private static final String USER_SUBMARINE_OID = "c4377f86-8be9-11e6-8ef5-c3c56ff64b09"; + private static final String USER_SUBMARINE_USERNAME = "submarine"; + private static final String USER_SUBMARINE_GIVEN_NAME = "Sub"; + private static final String USER_SUBMARINE_FAMILY_NAME = "Marine"; + private static final String USER_SUBMARINE_FULL_NAME = "Sub Marine"; + + private static final String INTENT_GROUP = "group"; + private static final String INTENT_OU_TOP = "ou-top"; + + private static final String USER_EMPTYHEAD_NAME = "emptyhead"; + + private static final String PROXY_ADDRES_ADDR_UPCASE = "smpt:ADDR"; + private static final String PROXY_ADDRES_ADDR_LOWCASE = "smpt:addr"; + + private static final String OBJECT_CATEGORY_PERSON = "CN=Person,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com"; + private static final String OBJECT_CATEGORY_GROUP = "CN=Group,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com"; + + private static final String USER_GUYBRUSH_PASSWORD_123 = "wanna.be.a.123"; + private static final String USER_GUYBRUSH_PASSWORD_333 = "wanna.be.a.333"; + + private static final String VERY_STRANGE_PARAMETER = "This iš a véry stándže p§räméteř!"; + + private boolean allowDuplicateSearchResults = false; + + protected String jackAccountOid; + protected String groupPiratesOid; + protected long jackLockoutTimestamp; + protected String accountBarbossaOid; + protected String orgMeleeIslandOid; + protected String groupMeleeIslandOid; + protected String ouMeleeIslandOid; + protected String roleMeleeIslandPiratesOid; + protected String groupMeleeIslandPiratesOid; + + private String accountSubmanOid; + + private String accountSubmarineOid; + + @Override + public String getStartSystemCommand() { + return null; + } + + @Override + public String getStopSystemCommand() { + return null; + } + + @Override + protected File getBaseDir() { + return TEST_DIR; + } + + @Override + protected String getSyncTaskOid() { + return "0f93d8d4-5fb4-11ea-8571-a3f090bf921f"; + } + + @Override + protected boolean useSsl() { + return true; + } + + @Override + protected String getLdapSuffix() { + return "DC=ad,DC=evolveum,DC=com"; + } + + @Override + protected String getLdapBindDn() { + return "CN=midpoint,CN=Users,DC=ad,DC=evolveum,DC=com"; + } + + @Override + protected String getLdapBindPassword() { + return "qwe.123"; + } + + @Override + protected int getSearchSizeLimit() { + return -1; + } + + @Override + public String getPrimaryIdentifierAttributeName() { + return "objectGUID"; + } + + @Override + protected String getPeopleLdapSuffix() { + return "CN=Users," + getLdapSuffix(); + } + + @Override + protected String getGroupsLdapSuffix() { + return "CN=Users," + getLdapSuffix(); + } + + protected String getLdapSubSuffix() { + return "DC=sub,DC=ad,DC=evolveum,DC=com"; + } + + protected String getPeopleLdapSubSuffix() { + return "CN=Users," + getLdapSubSuffix(); + } + + @Override + protected String getLdapAccountObjectClass() { + return "user"; + } + + @Override + protected String getLdapGroupObjectClass() { + return "group"; + } + + @Override + protected String getLdapGroupMemberAttribute() { + return "member"; + } + + private QName getAssociationGroupQName() { + return new QName(MidPointConstants.NS_RI, ASSOCIATION_GROUP_NAME); + } + + @Override + protected boolean allowDuplicateSearchResults() { + return allowDuplicateSearchResults; + } + + @Override + protected boolean isGroupMemberMandatory() { + return false; + } + + protected String getOrgsLdapSuffix() { + return "OU=Org," + getLdapSuffix(); + } + + private UserLdapConnectionConfig getSubLdapConnectionConfig() { + UserLdapConnectionConfig config = new UserLdapConnectionConfig(); + config.setLdapHost("hydra.ad.evolveum.com"); + config.setLdapPort(getLdapServerPort()); + config.setBindDn("CN=midpoint,CN=Users,DC=sub,DC=ad,DC=evolveum,DC=com"); + config.setBindPassword(getLdapBindPassword()); + config.setBaseContext(getLdapSubSuffix()); + return config; + } + + protected abstract File getReconciliationTaskFile(); + + protected abstract String getReconciliationTaskOid(); + + protected String getLdapConnectorClassName() { + return AD_CONNECTOR_TYPE; + } + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + + binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_OBJECT_GUID_NAME); + binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_UNICODE_PWD_NAME); + + // Users + repoAddObjectFromFile(USER_BARBOSSA_FILE, initResult); + repoAddObjectFromFile(USER_GUYBRUSH_FILE, initResult); + repoAddObjectFromFile(USER_SUBMAN_FILE, initResult); + repoAddObjectFromFile(USER_SUBMARINE_FILE, initResult); + + // Roles + repoAddObjectFromFile(ROLE_END_USER_FILE, initResult); + repoAddObjectFromFile(ROLE_PIRATES_FILE, initResult); + repoAddObjectFromFile(ROLE_SUBMISSIVE_FILE, initResult); + repoAddObjectFromFile(ROLE_META_ORG_FILE, initResult); + repoAddObjectFromFile(ROLE_META_ORG_GROUP_FILE, initResult); + + assignRole(USER_BARBOSSA_OID, ROLE_END_USER_OID); + + } + + @Test + public void test000Sanity() throws Exception { + assertLdapPassword(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME, ACCOUNT_JACK_PASSWORD); + cleanupDelete(toAccountDn(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME)); + cleanupDelete(toAccountDn(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME)); + cleanupDelete(toAccountDn(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME)); + cleanupDelete(getSubLdapConnectionConfig(), toAccountSubDn(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME)); + cleanupDelete(getSubLdapConnectionConfig(), toAccountSubDn(USER_SUBDOG_USERNAME, USER_SUBDOG_FULL_NAME)); + cleanupDelete(getSubLdapConnectionConfig(), toAccountSubDn(USER_SUBMARINE_USERNAME, USER_SUBMARINE_FULL_NAME)); + cleanupDelete(toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN)); + cleanupDelete(toAccountDn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN)); + cleanupDelete(toGroupDn(GROUP_MELEE_ISLAND_NAME)); + cleanupDelete(toGroupDn(GROUP_MELEE_ISLAND_ALT_NAME)); + cleanupDelete(toOrgGroupDn(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME)); + cleanupDelete(toOrgGroupDn(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME)); + cleanupDelete(toOrgDn(GROUP_MELEE_ISLAND_NAME)); + cleanupDelete("ou=underMelee," + toOrgDn(GROUP_MELEE_ISLAND_ALT_NAME)); + cleanupDelete(toOrgDn(GROUP_MELEE_ISLAND_ALT_NAME)); + } + + @Test + @Override + public void test020Schema() throws Exception { + // IntegrationTestTools.displayXml("Resource XML", resource); + accountObjectClassDefinition = assertAdResourceSchema(resource, getAccountObjectClass(), prismContext); + assertAdRefinedSchema(resource, getAccountObjectClass()); + assertExchangeSchema(resource, getAccountObjectClass(), prismContext); + + ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); + assertEquals("Unexpected number of schema definitions (limited by generation constraints)", 5, resourceSchema.getDefinitions().size()); + + assertLdapConnectorInstances(1); + } + + @Test + public void test100SeachJackBySamAccountName() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = createSamAccountNameQuery(ACCOUNT_JACK_SAM_ACCOUNT_NAME); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + when(); + SearchResultList> shadows = + modelService.searchObjects(ShadowType.class, query, null, task, result); + + // THEN + then(); + assertSuccess(result); + + assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); + + PrismObject shadow = shadows.get(0); + display("Shadow", shadow); + assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); + assertSid(shadow, ACCOUNT_JACK_SID); + assertObjectCategory(shadow, OBJECT_CATEGORY_PERSON); + jackAccountOid = shadow.getOid(); + +// assertConnectorOperationIncrement(2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = shadows.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(1); + } + + /** + * MID-3730 + */ + @Test + public void test101SeachJackByDn() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + String jackDn = toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME); + ObjectQuery query = createAccountShadowQueryByAttribute("dn", jackDn, resource); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + when(); + SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); + + // THEN + then(); + assertSuccess(result); + + assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); + + PrismObject shadow = shadows.get(0); + display("Shadow", shadow); + assertAccountShadow(shadow, jackDn); + assertSid(shadow, ACCOUNT_JACK_SID); + assertObjectCategory(shadow, OBJECT_CATEGORY_PERSON); + +// assertConnectorOperationIncrement(2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = shadows.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(1); + } + + /** + * Search for non-existent DN should return no results. It should NOT + * throw an error. + *

+ * MID-3730 + */ + @Test + public void test102SeachNotExistByDn() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + String dn = toAccountDn("idonoexist", "I am a Fiction"); + ObjectQuery query = createAccountShadowQueryByAttribute("dn", dn, resource); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + when(); + SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); + + // THEN + then(); + assertSuccess(result); + + assertEquals("Unexpected search result: " + shadows, 0, shadows.size()); + +// assertConnectorOperationIncrement(2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + assertLdapConnectorInstances(1); + } + + @Test + public void test105SeachPiratesByCn() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getGroupObjectClass(), prismContext); + ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter("cn", GROUP_PIRATES_NAME), prismContext); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + when(); + SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); + + // THEN + then(); + assertSuccess(result); + + assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); + + PrismObject shadow = shadows.get(0); + display("Shadow", shadow); + groupPiratesOid = shadow.getOid(); + assertObjectCategory(shadow, OBJECT_CATEGORY_GROUP); + +// assertConnectorOperationIncrement(1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = shadows.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(1); + } + + @Test + public void test110GetJack() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + long startOfTestMsTimestamp = getWin32Filetime(System.currentTimeMillis()); + + // WHEN + when(); + PrismObject shadow = modelService.getObject(ShadowType.class, jackAccountOid, null, task, result); + + // THEN + then(); + assertSuccess(result); + + display("Shadow", shadow); + assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); + jackAccountOid = shadow.getOid(); + + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + + assertAttribute(shadow, "dn", "CN=Jack Sparrow,CN=Users,DC=ad,DC=evolveum,DC=com"); + assertAttribute(shadow, "cn", ACCOUNT_JACK_FULL_NAME); + assertAttribute(shadow, "sn", "Sparrow"); + assertAttribute(shadow, "description", "The best pirate the world has ever seen"); + assertAttribute(shadow, "sAMAccountName", ACCOUNT_JACK_SAM_ACCOUNT_NAME); + assertObjectCategory(shadow, OBJECT_CATEGORY_PERSON); + List lastLogonValues = ShadowUtil.getAttributeValues(shadow, new QName(getResourceNamespace(), "lastLogon")); + assertEquals("Wrong number of lastLong values: " + lastLogonValues, 1, lastLogonValues.size()); + if (lastLogonValues.get(0) > startOfTestMsTimestamp) { + fail("Wrong lastLogon, expected it to be less than " + startOfTestMsTimestamp + ", but was " + lastLogonValues.get(0)); + } + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + assertLdapConnectorInstances(1); + } + + /** + * No paging. It should return all accounts. + */ + @Test + public void test150SeachAllAccounts() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + SearchResultList> searchResultList = doSearch(query, + NUMBER_OF_ACCOUNTS, task, result); + + // TODO: Why 14? Why not 1? + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 14); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * This is in one block. + */ + @Test + public void test152SeachFirst2Accounts() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(); + paging.setMaxSize(2); + query.setPaging(paging); + + SearchResultList> searchResultList = doSearch(query, 2, task, result); + + // TODO: Why 2? Why not 1? + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + @Test + public void test154SeachFirst11Accounts() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(); + paging.setMaxSize(11); + query.setPaging(paging); + + SearchResultList> searchResultList = doSearch(query, 11, task, result); + + // TODO: Why 2? Why not 1? + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + @Test + public void test162SeachFirst2AccountsOffset0() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(); + paging.setOffset(0); + paging.setMaxSize(2); + query.setPaging(paging); + + SearchResultList> searchResultList = doSearch(query, 2, task, result); + + // TODO: Why 2? Why not 1? + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * There is offset, so VLV should be used. + * No explicit sorting. + */ + @Test + public void test172Search2AccountsOffset1() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(1, 2); + query.setPaging(paging); + + SearchResultList> searchResultList = doSearch(query, 2, task, result); + + // TODO: Why 2? Why not 1? + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * There is offset, so VLV should be used. + * No explicit sorting. + */ + @Test + public void test174SeachFirst11AccountsOffset2() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(2, 11); + query.setPaging(paging); + + allowDuplicateSearchResults = true; + + // WHEN + SearchResultList> searchResultList = doSearch(query, 11, task, result); + + // THEN + allowDuplicateSearchResults = false; + + // TODO: Why 2? Why not 1? + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * There is offset, so VLV should be used. + * Explicit sorting. + */ + @Test + public void test182Search2AccountsOffset1SortCn() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(1, 2); + paging.setOrdering(getAttributePath(resource, "cn"), OrderDirection.ASCENDING); + query.setPaging(paging); + + SearchResultList> shadows = doSearch(query, 2, task, result); + + assertAccountShadow(shadows.get(0), "CN=Adolf Supperior,CN=Users,DC=ad,DC=evolveum,DC=com"); +// assertAccountShadow(shadows.get(1), "CN=DiscoverySearchMailbox {D919BA05-46A6-415f-80AD-7E09334BB852},CN=Users,DC=ad,DC=evolveum,DC=com"); + + // TODO: Why 2? Why not 1? + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = shadows.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + @Test + public void test200AssignAccountBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + assignAccountToUser(USER_BARBOSSA_OID, getResourceOid(), null, task, result); + + // THEN + then(); + assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "title", null); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getShadowModel(shadowOid); + display("Shadow (model)", shadow); + accountBarbossaOid = shadow.getOid(); + Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); + String accountBarbossaIcfUid = (String) identifiers.iterator().next().getRealValue(); + assertNotNull("No identifier in " + shadow, accountBarbossaIcfUid); + + assertEquals("Wrong ICFS UID", + formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), + accountBarbossaIcfUid); + + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); + + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); + + // MID-4624 + ResourceAttribute createTimestampAttribute = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, "createTimeStamp")); + assertNotNull("No createTimestamp in " + shadow, createTimestampAttribute); + XMLGregorianCalendar createTimestamp = createTimestampAttribute.getRealValue(); + long createTimestampMillis = XmlTypeConverter.toMillis(createTimestamp); + // LDAP server may be on a different host. Allow for some clock offset. + TestUtil.assertBetween("Wrong createTimestamp in " + shadow, roundTsDown(tsStart) - 120000, roundTsUp(tsEnd) + 120000, createTimestampMillis); + + assertObjectCategory(shadow, OBJECT_CATEGORY_PERSON); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test210ModifyAccountBarbossaTitle() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta delta = prismContext.deltaFactory().object() + .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); + QName attrQName = new QName(MidPointConstants.NS_RI, ATTRIBUTE_TITLE_NAME); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( + ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, "Captain"); + delta.addModification(attrDelta); + + // WHEN + when(); + executeChanges(delta, null, task, result); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_TITLE_NAME, "Captain"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test212ModifyAccountBarbossaShowInAdvancedViewOnlyTrue() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta delta = prismContext.deltaFactory().object() + .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); + QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( + ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); + delta.addModification(attrDelta); + + // WHEN + when(); + executeChanges(delta, null, task, result); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "showInAdvancedViewOnly", "TRUE"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertLdapConnectorInstances(2); + } + + /** + * Modify USER, test boolean value mapping. + */ + @Test + public void test213ModifyUserBarbossaShowInAdvancedViewOnlyFalse() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta delta = prismContext.deltaFactory().object() + .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); + QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( + ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); + delta.addModification(attrDelta); + + // WHEN + when(); + modifyUserReplace(USER_BARBOSSA_OID, ItemPath.create(UserType.F_EXTENSION, EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME), + task, result, Boolean.FALSE); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "showInAdvancedViewOnly", "FALSE"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertLdapConnectorInstances(2); + } + + /** + * Just normal modification of proxyAddress, directly on the account. + * As proxyAddress is multivalue, this is ADD and not REPLACE. This is what GUI would do. + * No previous value for proxyAddress is set in the AD account. + * MID-5330 + */ + @Test + public void test214ModifyAccountBarbossaProxyAddressesSimple() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta delta = prismContext.deltaFactory().object() + .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); + QName attrQName = new QName(MidPointConstants.NS_RI, ATTRIBUTE_PROXY_ADDRESSES_NAME); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + assertNotNull("No definition for attribute " + attrQName, attrDef); + PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationAddProperty( + ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, PROXY_ADDRES_ADDR_UPCASE); + delta.addModification(attrDelta); + + // WHEN + when(); + executeChanges(delta, null, task, result); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_PROXY_ADDRESSES_NAME, PROXY_ADDRES_ADDR_UPCASE); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + +// assertLdapConnectorInstances(2); + } + + /** + * MID-4385 + */ + @Test + public void test216ModifyAccountBarbossaUserParameters() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta delta = prismContext.deltaFactory().object() + .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); + QName attrQName = new QName(MidPointConstants.NS_RI, ATTRIBUTE_USER_PARAMETERS_NAME); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + assertNotNull("No definition for attribute " + attrQName, attrDef); + PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( + ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, VERY_STRANGE_PARAMETER); + delta.addModification(attrDelta); + + // WHEN + when(); + executeChanges(delta, null, task, result); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_PARAMETERS_NAME, VERY_STRANGE_PARAMETER); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertModelShadow(shadowOid) + .attributes() + .attribute(ATTRIBUTE_USER_PARAMETERS_NAME) + .assertRealValues(VERY_STRANGE_PARAMETER); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test220ModifyUserBarbossaPasswordSelfServicePassword1() throws Exception { + testModifyUserBarbossaPasswordSelfServiceSuccess( + USER_BARBOSSA_PASSWORD, USER_BARBOSSA_PASSWORD_AD_1); + } + + /** + * Try to set the same password again. If this is "admin mode" (no runAs capability) + * the such change should be successful. In "selfservice mode" (runAs capability - in subclass) + * this change should fail. + */ + @Test + public void test222ModifyUserBarbossaPasswordSelfServicePassword1Again() throws Exception { + testModifyUserBarbossaPasswordSelfServiceSuccess( + USER_BARBOSSA_PASSWORD_AD_1, USER_BARBOSSA_PASSWORD_AD_1); + } + + /** + * Change to different password. This should go well for both admin and self-service. + * MID-5242 + */ + @Test + public void test224ModifyUserBarbossaPasswordSelfServicePassword2() throws Exception { + testModifyUserBarbossaPasswordSelfServiceSuccess( + USER_BARBOSSA_PASSWORD_AD_1, USER_BARBOSSA_PASSWORD_AD_2); + } + + /** + * Change password back to the first password. This password was used before. + * In admin mode this should go well. Admin can set password to anything. + * But in self-service mode (in subclass) this should fail due to password history check. + */ + @Test + public void test226ModifyUserBarbossaPasswordSelfServicePassword1AgainAgain() throws Exception { + testModifyUserBarbossaPasswordSelfServiceSuccess( + USER_BARBOSSA_PASSWORD_AD_2, USER_BARBOSSA_PASSWORD_AD_1); + } + + protected void testModifyUserBarbossaPasswordSelfServiceSuccess(String oldPassword, String newPassword) throws Exception { + // GIVEN + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, oldPassword); + + login(USER_BARBOSSA_USERNAME); + + Task task = getTestTask(); + task.setChannel(SchemaConstants.CHANNEL_GUI_SELF_SERVICE_URI); + OperationResult result = task.getResult(); + + ObjectDelta objectDelta = createOldNewPasswordDelta(USER_BARBOSSA_OID, + oldPassword, newPassword); + + // WHEN + when(); + executeChanges(objectDelta, null, task, result); + + // THEN + then(); + login(USER_ADMINISTRATOR_USERNAME); + assertSuccess(result); + + assertBarbossaEnabled(newPassword); + + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, newPassword); + + assertLdapConnectorInstances(2); + } + + protected void testModifyUserBarbossaPasswordSelfServiceFailure( + String oldPassword, String newPassword) throws Exception { + // GIVEN + login(USER_BARBOSSA_USERNAME); + + Task task = getTestTask(); + task.setChannel(SchemaConstants.CHANNEL_GUI_SELF_SERVICE_URI); + OperationResult result = task.getResult(); + + ObjectDelta objectDelta = createOldNewPasswordDelta(USER_BARBOSSA_OID, + oldPassword, newPassword); + + // WHEN + when(); + executeChanges(objectDelta, null, task, result); + + // THEN + then(); + login(USER_ADMINISTRATOR_USERNAME); + assertPartialError(result); + + assertBarbossaEnabled(newPassword); + assertUserAfter(USER_BARBOSSA_OID) + .assertPassword(newPassword); + + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, oldPassword); + + assertLdapConnectorInstances(2); + } + + @Test + public void test230DisableUserBarbossa() throws Exception { + // precondition + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_AD_1); + + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyUserReplace(USER_BARBOSSA_OID, + SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, + task, result, ActivationStatusType.DISABLED); + + // THEN + then(); + assertSuccess(result); + + assertBarbossaDisabled(USER_BARBOSSA_PASSWORD_AD_1); + } + + /** + * MID-4041 + */ + @Test + public void test232ReconcileBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + reconcileUser(USER_BARBOSSA_OID, task, result); + + // THEN + then(); + assertSuccess(result); + + assertBarbossaDisabled(USER_BARBOSSA_PASSWORD_AD_1); + } + + /** + * MID-4041 + */ + @Test + public void test236EnableUserBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyUserReplace(USER_BARBOSSA_OID, + SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, + task, result, ActivationStatusType.ENABLED); + + // THEN + then(); + assertSuccess(result); + + assertBarbossaEnabled(USER_BARBOSSA_PASSWORD_AD_1); + + assertLdapConnectorInstances(2); + } + + /** + * MID-4041 + */ + @Test + public void test237ReconcileBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + reconcileUser(USER_BARBOSSA_OID, task, result); + + // THEN + then(); + assertSuccess(result); + + assertBarbossaEnabled(USER_BARBOSSA_PASSWORD_AD_1); + + assertLdapConnectorInstances(2); + } + + /** + * MID-4041 + */ + @Test + public void test238DisableUserBarbossaRawAndReconcile() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + modifyUserReplace(USER_BARBOSSA_OID, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, + ModelExecuteOptions.createRaw(), task, result, ActivationStatusType.DISABLED); + + // WHEN + when(); + reconcileUser(USER_BARBOSSA_OID, task, result); + + // THEN + then(); + assertSuccess(result); + + assertBarbossaDisabled(USER_BARBOSSA_PASSWORD_AD_1); + + assertLdapConnectorInstances(2); + } + + /** + * MID-4041 + */ + @Test + public void test239EnableUserBarbossaRawAndReconcile() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + modifyUserReplace(USER_BARBOSSA_OID, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, + ModelExecuteOptions.createRaw(), task, result, ActivationStatusType.ENABLED); + + // WHEN + when(); + reconcileUser(USER_BARBOSSA_OID, task, result); + + // THEN + then(); + assertSuccess(result); + + assertBarbossaEnabled(USER_BARBOSSA_PASSWORD_AD_1); + + assertLdapConnectorInstances(2); + } + + protected PrismObject assertBarbossaEnabled(String ldapPassword) throws Exception { + PrismObject user = getUser(USER_BARBOSSA_OID); + assertAdministrativeStatus(user, ActivationStatusType.ENABLED); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "title", "Captain"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + assertAttribute(entry, ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME, "FALSE"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountEnabled(shadow); + + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, ldapPassword); + + return user; + } + + private void assertBarbossaDisabled(String password) throws Exception { + assertLdapConnectorInstances(2); + + PrismObject user = getUser(USER_BARBOSSA_OID); + assertAdministrativeStatus(user, ActivationStatusType.DISABLED); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + displayValue("disabled Barbossa entry", entry); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); + + assertAttribute(entry, ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME, "TRUE"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountDisabled(shadow); + + try { + assertLdapPassword(null, entry, password); + AssertJUnit.fail("Password authentication works, but it should fail"); + } catch (SecurityException e) { + // this is expected + } + + assertLdapConnectorInstances(2); + } + + /** + * This should create account with a group. And the account should be disabled. + */ + @Test + public void test250AssignGuybrushPirates() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + +// ProtectedStringType userPasswordPs = new ProtectedStringType(); +// userPasswordPs.setClearValue(USER_GUYBRUSH_PASSWORD_333); +// modifyUserReplace(USER_GUYBRUSH_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); + modifyUserReplace(USER_GUYBRUSH_OID, + SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, + task, result, ActivationStatusType.DISABLED); + + // WHEN + when(); + assignRole(USER_GUYBRUSH_OID, ROLE_PIRATES_OID, task, result); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + displayValue("Entry", entry); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); + + assertLdapGroupMember(entry, GROUP_PIRATES_NAME); + + PrismObject user = getUser(USER_GUYBRUSH_OID); + assertAdministrativeStatus(user, ActivationStatusType.DISABLED); + String shadowOid = getSingleLinkOid(user); + + PrismObject shadow = getObject(ShadowType.class, shadowOid); + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + assertAccountDisabled(shadow); + +// try { +// assertLdapPassword(null, entry, USER_GUYBRUSH_PASSWORD_333); +// AssertJUnit.fail("Password authentication works, but it should fail"); +// } catch (SecurityException e) { +// // this is expected, account is disabled +// } + + assertLdapConnectorInstances(2); + } + + @Test + public void test255ModifyUserGuybrushPassword() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ProtectedStringType userPasswordPs = new ProtectedStringType(); + userPasswordPs.setClearValue(USER_GUYBRUSH_PASSWORD_123); + + // WHEN + when(); + modifyUserReplace(USER_GUYBRUSH_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + displayValue("Guybrush entry after", entry); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); + + try { + assertLdapPassword(null, entry, USER_GUYBRUSH_PASSWORD_123); + AssertJUnit.fail("Password authentication works, but it should fail"); + } catch (SecurityException e) { + // this is expected, account is disabled + } + +// assertLdapConnectorInstances(2); + } + + @Test + public void test260EnableGyubrush() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyUserReplace(USER_GUYBRUSH_OID, + SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, + task, result, ActivationStatusType.ENABLED); + + // THEN + then(); + assertSuccess(result); + + PrismObject user = getUser(USER_GUYBRUSH_OID); + assertAdministrativeStatus(user, ActivationStatusType.ENABLED); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountEnabled(shadow); + + assertLdapPassword(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME, "wanna.be.a.123"); + + assertLdapConnectorInstances(2); + } + + /** + * Try to create an account without password. This should end up with an error. + * A reasonable error. + * MID-4046 + */ + @Test + public void test270AssignAccountToEmptyhead() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + PrismObject userBefore = createUser(USER_EMPTYHEAD_NAME, USER_EMPTYHEAD_NAME, true); + display("User before", userBefore); + addObject(userBefore); + String userEmptyheadOid = userBefore.getOid(); + + // WHEN + when(); + assignAccountToUser(userEmptyheadOid, getResourceOid(), null, task, result); + + // THEN + then(); + assertPartialError(result); + + assertMessageContains(result.getMessage(), "does not meet the length, complexity, or history requirement"); + + assertLdapConnectorInstances(2); + } + + /** + * Just make random test connection between the tests. Make sure that the + * test does not break anything. If it does the next tests will simply fail. + */ + @Test + public void test295TestConnection() throws Exception { + // GIVEN + Task task = getTestTask(); + + // WHEN + when(); + OperationResult testResult = modelService.testResource(getResourceOid(), task); + + // THEN + then(); + display("Test connection result", testResult); + TestUtil.assertSuccess("Test connection result", testResult); + + // Test is disposing connector facade and the entire connector pool. + // Therefore we are back at 1 instance. + assertLdapConnectorInstances(1); + } + + @Test + public void test300AssignBarbossaPirates() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + assignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + displayValue("Entry", entry); + assertAttribute(entry, "title", "Captain"); + + assertLdapGroupMember(entry, GROUP_PIRATES_NAME); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + PrismObject shadow = getObject(ShadowType.class, shadowOid); + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + + assertLdapConnectorInstances(1); + } + + @Test + public void test390ModifyUserBarbossaRename() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta objectDelta = createModifyUserReplaceDelta(USER_BARBOSSA_OID, UserType.F_NAME, + PrismTestUtil.createPolyString(USER_CPTBARBOSSA_USERNAME)); + objectDelta.addModificationReplaceProperty(UserType.F_FULL_NAME, + PrismTestUtil.createPolyString(USER_CPTBARBOSSA_FULL_NAME)); + Collection> deltas = MiscSchemaUtil.createCollection(objectDelta); + + // WHEN + when(); + modelService.executeChanges(deltas, null, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); + assertAttribute(entry, "title", "Captain"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + display("Shadow after rename (model)", shadow); + + PrismObject repoShadow = repositoryService.getObject(ShadowType.class, shadowOid, null, result); + display("Shadow after rename (repo)", repoShadow); + + assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + +// assertLdapConnectorInstances(2); + } + + // TODO: create account with a group membership + + @Test + public void test395UnAssignBarbossaPirates() throws Exception { + // TODO: do this on another account. There is a bad interference with rename. + + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + unassignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); + displayValue("Entry", entry); + assertAttribute(entry, "title", "Captain"); + + assertLdapNoGroupMember(entry, GROUP_PIRATES_NAME); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + PrismObject shadow = getObject(ShadowType.class, shadowOid); + IntegrationTestTools.assertNoAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test399UnAssignAccountBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + unassignAccountFromUser(USER_BARBOSSA_OID, getResourceOid(), null, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertNoLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); + + PrismObject user = getUser(USER_BARBOSSA_OID); + assertNoLinkedAccount(user); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test500AddOrgMeleeIsland() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + PrismObject org = instantiateObject(OrgType.class); + OrgType orgType = org.asObjectable(); + orgType.setName(new PolyStringType(GROUP_MELEE_ISLAND_NAME)); + AssignmentType metaroleAssignment = new AssignmentType(); + ObjectReferenceType metaroleRef = new ObjectReferenceType(); + metaroleRef.setOid(ROLE_META_ORG_OID); + metaroleRef.setType(RoleType.COMPLEX_TYPE); + metaroleAssignment.setTargetRef(metaroleRef); + orgType.getAssignment().add(metaroleAssignment); + + // WHEN + when(); + addObject(org, task, result); + + // THEN + then(); + assertSuccess(result); + + orgMeleeIslandOid = org.getOid(); + assertLdapGroup(GROUP_MELEE_ISLAND_NAME); + assertLdapOrg(GROUP_MELEE_ISLAND_NAME); + + org = getObject(OrgType.class, orgMeleeIslandOid); + groupMeleeIslandOid = getLinkRefOid(org, getResourceOid(), ShadowKindType.ENTITLEMENT, INTENT_GROUP); + ouMeleeIslandOid = getLinkRefOid(org, getResourceOid(), ShadowKindType.GENERIC, INTENT_OU_TOP); + assertLinks(org, 2); + + PrismObject shadowGroup = getShadowModel(groupMeleeIslandOid); + display("Shadow: group (model)", shadowGroup); + + PrismObject shadowOu = getShadowModel(ouMeleeIslandOid); + display("Shadow: ou (model)", shadowOu); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test510AssignGuybrushMeleeIsland() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + assignOrg(USER_GUYBRUSH_OID, orgMeleeIslandOid, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + + PrismObject user = getUser(USER_GUYBRUSH_OID); + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getShadowModel(shadowOid); + display("Shadow (model)", shadow); + + assertLdapGroupMember(entry, GROUP_MELEE_ISLAND_NAME); + + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupMeleeIslandOid); + +// assertLdapConnectorInstances(2); + } + + /** + * Create role under the Melee Island org. This creates group in the orgstruct. + */ + @Test + public void test515AddOrgGroupMeleeIslandPirates() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + PrismObject role = instantiateObject(RoleType.class); + RoleType roleType = role.asObjectable(); + roleType.setName(new PolyStringType(GROUP_MELEE_ISLAND_PIRATES_NAME)); + + AssignmentType metaroleAssignment = new AssignmentType(); + ObjectReferenceType metaroleRef = new ObjectReferenceType(); + metaroleRef.setOid(ROLE_META_ORG_GROUP_OID); + metaroleRef.setType(RoleType.COMPLEX_TYPE); + metaroleAssignment.setTargetRef(metaroleRef); + roleType.getAssignment().add(metaroleAssignment); + + AssignmentType orgAssignment = new AssignmentType(); + ObjectReferenceType orgRef = new ObjectReferenceType(); + orgRef.setOid(orgMeleeIslandOid); + orgRef.setType(OrgType.COMPLEX_TYPE); + orgAssignment.setTargetRef(orgRef); + roleType.getAssignment().add(orgAssignment); + + // WHEN + when(); + addObject(role, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + roleMeleeIslandPiratesOid = role.getOid(); + // TODO: assert LDAP object + + assertLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); + + PrismObject roleAfter = getObject(RoleType.class, roleMeleeIslandPiratesOid); + display("Role after", roleAfter); + groupMeleeIslandPiratesOid = getSingleLinkOid(roleAfter); + PrismObject shadow = getShadowModel(groupMeleeIslandPiratesOid); + display("Shadow (model)", shadow); + } + + /** + * Rename org unit. MidPoint should rename OU and ordinary group. + * AD will rename the group in the orgstruct automatically. We need to + * make sure that we can still access that group. + */ + @Test + public void test520RenameMeleeIsland() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + renameObject(OrgType.class, orgMeleeIslandOid, GROUP_MELEE_ISLAND_ALT_NAME, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + PrismObject orgAfter = getObject(OrgType.class, orgMeleeIslandOid); + groupMeleeIslandOid = getLinkRefOid(orgAfter, getResourceOid(), ShadowKindType.ENTITLEMENT, INTENT_GROUP); + ouMeleeIslandOid = getLinkRefOid(orgAfter, getResourceOid(), ShadowKindType.GENERIC, INTENT_OU_TOP); + assertLinks(orgAfter, 2); + + PrismObject shadowGroup = getShadowModel(groupMeleeIslandOid); + display("Shadow: group (model)", shadowGroup); + + PrismObject shadowOu = getShadowModel(ouMeleeIslandOid); + display("Shadow: ou (model)", shadowOu); + + assertLdapGroup(GROUP_MELEE_ISLAND_ALT_NAME); + assertNoLdapGroup(GROUP_MELEE_ISLAND_NAME); + + assertLdapOrg(GROUP_MELEE_ISLAND_ALT_NAME); + assertNoLdapOrg(GROUP_MELEE_ISLAND_NAME); + + assertLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME); + assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); + + Entry entryGuybrush = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + + PrismObject user = getUser(USER_GUYBRUSH_OID); + String shadowAccountOid = getSingleLinkOid(user); + PrismObject shadowAccount = getShadowModel(shadowAccountOid); + display("Shadow: account (model)", shadowAccount); + + assertLdapGroupMember(entryGuybrush, GROUP_MELEE_ISLAND_ALT_NAME); + + IntegrationTestTools.assertAssociation(shadowAccount, getAssociationGroupQName(), groupMeleeIslandOid); + +// assertLdapConnectorInstances(2); + } + + /** + * AD renamed the pirate groups by itself. MidPoint does not know about it. + * The GUID that is stored in the shadow is still OK. But the DN is now out + * of date. Try to update the group. Make sure it works. + * It is expected that the GUI will be used as a primary identifier. + * Note: just reading the group will NOT work. MidPoint is too smart + * for that. It will transparently fix the situation. + */ + @Test + public void test522ModifyMeleeIslandPirates() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyObjectReplaceProperty(ShadowType.class, groupMeleeIslandPiratesOid, + ItemPath.create(ShadowType.F_ATTRIBUTES, new QName(MidPointConstants.NS_RI, "description")), + task, result, GROUP_MELEE_ISLAND_PIRATES_DESCRIPTION); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entryOrgGroup = assertLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME); + assertAttribute(entryOrgGroup, "description", GROUP_MELEE_ISLAND_PIRATES_DESCRIPTION); + + assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test524GetMeleeIslandPirates() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + PrismObject shadow = modelService.getObject(ShadowType.class, groupMeleeIslandPiratesOid, null, task, result); + + // THEN + then(); + assertSuccess(result); + + display("Shadow after", shadow); + assertNotNull(shadow); + + assertLdapGroup(GROUP_MELEE_ISLAND_ALT_NAME); + assertNoLdapGroup(GROUP_MELEE_ISLAND_NAME); + assertLdapOrg(GROUP_MELEE_ISLAND_ALT_NAME); + assertNoLdapOrg(GROUP_MELEE_ISLAND_NAME); + Entry entryOrgGroup = assertLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME); + displayValue("Melee org", entryOrgGroup); + assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); + } + + @Test + public void test595DeleteOrgGroupMeleeIslandPirates() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + deleteObject(RoleType.class, roleMeleeIslandPiratesOid, task, result); + + // THEN + then(); + assertSuccess(result); + + assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME); + assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); + + assertNoObject(ShadowType.class, groupMeleeIslandPiratesOid); + +// assertLdapConnectorInstances(2); + } + + /** + * We create "underMelee" org that gets into the way of the delete. + * Melee cannot be deleted in an ordinary way. "tree delete" control must + * be used. This is configured in the connector config. + *

+ * MID-5935 + */ + @Test + public void test599DeleteOrgMeleeIsland() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + createUnderMeleeEntry(); + + // WHEN + when(); + deleteObject(OrgType.class, orgMeleeIslandOid, task, result); + + // THEN + then(); + assertSuccess(result); + + assertNoLdapGroup(GROUP_MELEE_ISLAND_NAME); + assertNoLdapGroup(GROUP_MELEE_ISLAND_ALT_NAME); + assertNoLdapOrg(GROUP_MELEE_ISLAND_NAME); + assertNoLdapOrg(GROUP_MELEE_ISLAND_ALT_NAME); + + assertNoObject(ShadowType.class, groupMeleeIslandOid); + assertNoObject(ShadowType.class, ouMeleeIslandOid); + +// assertLdapConnectorInstances(2); + } + + protected void createUnderMeleeEntry() throws LdapException, IOException { + // This OU just gets into the way of the delete. + Entry entry = new DefaultEntry("ou=underMelee," + toOrgDn(GROUP_MELEE_ISLAND_ALT_NAME), + "objectclass", "organizationalUnit", + "ou", "underMelee"); + displayValue("underMelee org", entry); + addLdapEntry(entry); + } + + @Test + public void test600AssignAccountSubman() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + assignRole(USER_SUBMAN_OID, ROLE_SUBMISSIVE_OID, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); + displayValue("Sub entry", entry); + assertAttribute(entry, "title", null); + + PrismObject userAfter = getUser(USER_SUBMAN_OID); + String shadowOid = getSingleLinkOid(userAfter); + PrismObject shadow = getShadowModel(shadowOid); + display("Shadow (model)", shadow); + accountSubmanOid = shadow.getOid(); + Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); + String accountBarbossaIcfUid = (String) identifiers.iterator().next().getRealValue(); + assertNotNull("No identifier in " + shadow, accountBarbossaIcfUid); + + assertEquals("Wrong ICFS UID", + formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), + accountBarbossaIcfUid); + + assertLdapPassword(getSubLdapConnectionConfig(), USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME, USER_SUBMAN_PASSWORD); + + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + // MID-4624 + ResourceAttribute createTimestampAttribute = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, "createTimeStamp")); + assertNotNull("No createTimestamp in " + shadow, createTimestampAttribute); + XMLGregorianCalendar createTimestamp = createTimestampAttribute.getRealValue(); + long createTimestampMillis = XmlTypeConverter.toMillis(createTimestamp); + // LDAP server may be on a different host. Allow for some clock offset. + TestUtil.assertBetween("Wrong createTimestamp in " + shadow, roundTsDown(tsStart) - 120000, roundTsUp(tsEnd) + 120000, createTimestampMillis); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test610ModifyUserSubmanTitle() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyUserReplace(USER_SUBMAN_OID, UserType.F_TITLE, task, result, + createPolyString("Underdog")); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); + displayValue("Sub entry", entry); + assertAttribute(entry, "title", "Underdog"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_SUBMAN_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountSubmanOid, shadowOid); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test620ModifyUserSubmanPassword() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ProtectedStringType userPasswordPs = new ProtectedStringType(); + userPasswordPs.setClearValue("SuB.321"); + + // WHEN + when(); + modifyUserReplace(USER_SUBMAN_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); + assertAttribute(entry, "title", "Underdog"); + assertLdapPassword(getSubLdapConnectionConfig(), USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME, "SuB.321"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_SUBMAN_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountSubmanOid, shadowOid); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test630DisableUserSubman() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyUserReplace(USER_SUBMAN_OID, + SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, + task, result, ActivationStatusType.DISABLED); + + // THEN + then(); + assertSuccess(result); + +// assertLdapConnectorInstances(2); + + PrismObject user = getUser(USER_SUBMAN_OID); + assertAdministrativeStatus(user, ActivationStatusType.DISABLED); + + Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountDisabled(shadow); + + try { + assertLdapPassword(getSubLdapConnectionConfig(), USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME, "SuB.321"); + AssertJUnit.fail("Password authentication works, but it should fail"); + } catch (SecurityException e) { + // this is expected + } + +// assertLdapConnectorInstances(2); + } + + @Test + public void test639EnableUserSubman() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyUserReplace(USER_SUBMAN_OID, + SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, + task, result, ActivationStatusType.ENABLED); + + // THEN + then(); + assertSuccess(result); + + PrismObject user = getUser(USER_SUBMAN_OID); + assertAdministrativeStatus(user, ActivationStatusType.ENABLED); + + Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountEnabled(shadow); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test690ModifyUserSubmanRename() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta objectDelta = createModifyUserReplaceDelta(USER_SUBMAN_OID, UserType.F_NAME, + createPolyString(USER_SUBDOG_USERNAME)); + objectDelta.addModificationReplaceProperty(UserType.F_FULL_NAME, + createPolyString(USER_SUBDOG_FULL_NAME)); + + // WHEN + when(); + executeChanges(objectDelta, null, task, result); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapSubAccount(USER_SUBDOG_USERNAME, USER_SUBDOG_FULL_NAME); + assertAttribute(entry, "title", "Underdog"); + + PrismObject user = getUser(USER_SUBMAN_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountSubmanOid, shadowOid); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + display("Shadow after rename (model)", shadow); + + PrismObject repoShadow = repositoryService.getObject(ShadowType.class, shadowOid, null, result); + display("Shadow after rename (repo)", repoShadow); + + assertNoLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test699UnAssignAccountSubdog() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + unassignRole(USER_SUBMAN_OID, ROLE_SUBMISSIVE_OID, task, result); + + // THEN + then(); + assertSuccess(result); + + assertNoLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); + assertNoLdapSubAccount(USER_SUBDOG_USERNAME, USER_SUBDOG_FULL_NAME); + + PrismObject user = getUser(USER_SUBMAN_OID); + assertNoLinkedAccount(user); + +// assertLdapConnectorInstances(2); + } + + /** + * Create account and modify it in a very quick succession. + * This test is designed to check if we can live with a long + * global catalog update delay. + * MID-2926 + */ + @Test + public void test700AssignAccountSubmarineAndModify() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + assignRole(USER_SUBMARINE_OID, ROLE_SUBMISSIVE_OID, task, result); + + modifyUserReplace(USER_SUBMARINE_OID, UserType.F_TITLE, task, result, + PrismTestUtil.createPolyString("Underseadog")); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapSubAccount(USER_SUBMARINE_USERNAME, USER_SUBMARINE_FULL_NAME); + displayValue("Sub entry", entry); + assertAttribute(entry, "title", "Underseadog"); + + PrismObject userAfter = getUser(USER_SUBMARINE_OID); + String shadowOid = getSingleLinkOid(userAfter); + PrismObject shadow = getShadowModel(shadowOid); + display("Shadow (model)", shadow); + accountSubmarineOid = shadow.getOid(); + Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); + String accountIcfUid = (String) identifiers.iterator().next().getRealValue(); + assertNotNull("No identifier in " + shadow, accountIcfUid); + + assertEquals("Wrong ICFS UID", + formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), + accountIcfUid); + + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + } + + @Test + public void test809UnAssignAccountSubmarine() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + unassignRole(USER_SUBMARINE_OID, ROLE_SUBMISSIVE_OID, task, result); + + // THEN + then(); + assertSuccess(result); + + assertNoLdapSubAccount(USER_SUBMARINE_USERNAME, USER_SUBMARINE_FULL_NAME); + + PrismObject user = getUser(USER_SUBMARINE_OID); + assertNoLinkedAccount(user); + } + + @Test + public void test850ReconcileAccounts() throws Exception { + // GIVEN + assertUsers(6); + + // WHEN + when(); + addTask(getReconciliationTaskFile()); + + waitForTaskFinish(getReconciliationTaskOid(), true); + + // THEN + then(); + + assertUsers(15); + // TODO + +// assertLdapConnectorInstances(2); + } + + // DISABLED because we do not know how to properly configure sync privileges in a AD forrest. + // More experiments are needed, but only after we migrate our old AD servers. + @Test(enabled=false) + public void test900ImportSyncTask() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + addObject(getSyncTaskFile(), task, result); + + // THEN + then(); + assertSuccess(result); + + waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); + + long tsEnd = System.currentTimeMillis(); + + assertStepSyncToken(getSyncTaskOid(), 0, tsStart, tsEnd); + } + + // DISABLED because we do not know how to properly configure sync privileges in a AD forrest. + // More experiments are needed, but only after we migrate our old AD servers. + @Test(enabled=false) + public void test901SyncAddAccountHt() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + addLdapAccount(ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN); + waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); + + // THEN + then(); + assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + displayUsers(); + + PrismObject user = findUserByUsername(ACCOUNT_HT_UID); + assertNotNull("No user " + ACCOUNT_HT_UID + " created", user); + assertUser(user, user.getOid(), ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN); + + assertStepSyncToken(getSyncTaskOid(), 1, tsStart, tsEnd); + } + + protected void assertStepSyncToken(String syncTaskOid, int step, long tsStart, long tsEnd) + throws ObjectNotFoundException, SchemaException { + OperationResult result = createOperationResult("assertStepSyncToken"); + Task task = taskManager.getTaskPlain(syncTaskOid, result); + PrismProperty syncTokenProperty = task.getExtensionPropertyOrClone(SchemaConstants.SYNC_TOKEN); + assertNotNull("No sync token", syncTokenProperty); + assertNotNull("No sync token value", syncTokenProperty.getRealValue()); + assertNotNull("Empty sync token value", StringUtils.isBlank(syncTokenProperty.getRealValue())); + assertSuccess(result); + } + + @Override + protected void assertAccountShadow(PrismObject shadow, String dn) throws SchemaException { + super.assertAccountShadow(shadow, dn); + ResourceAttribute primaryIdAttr = ShadowUtil.getAttribute(shadow, getPrimaryIdentifierAttributeQName()); + assertNotNull("No primary identifier (" + getPrimaryIdentifierAttributeQName() + " in " + shadow, primaryIdAttr); + String primaryId = primaryIdAttr.getRealValue(); + assertTrue("Unexpected chars in primary ID: '" + primaryId + "'", primaryId.matches("[a-z0-9\\-]+")); + + ResourceAttribute objectSidAttr = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, ATTRIBUTE_OBJECT_SID_NAME)); + assertNotNull("No SID in " + shadow, objectSidAttr); + display("SID of " + dn + ": " + objectSidAttr); + } + + protected void assertSid(PrismObject shadow, String expectedSid) { + ResourceAttribute objectSidAttr = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, ATTRIBUTE_OBJECT_SID_NAME)); + assertNotNull("No SID in " + shadow, objectSidAttr); + display("SID of " + shadow + ": " + objectSidAttr); + assertEquals("Wrong SID in " + shadow, expectedSid, objectSidAttr.getRealValue()); + } + + private void assertObjectCategory(PrismObject shadow, String expectedObjectCategory) { + ResourceAttribute objectCategoryAttr = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, ATTRIBUTE_OBJECT_CATEGORY_NAME)); + assertNotNull("No objectCategory in " + shadow, objectCategoryAttr); + display("objectCategory of " + shadow + ": " + objectCategoryAttr); + assertEquals("Wrong objectCategory in " + shadow, expectedObjectCategory, objectCategoryAttr.getRealValue()); + } + + @Override + protected Entry assertLdapAccount(String samAccountName, String cn) throws LdapException, IOException, CursorException { + Entry entry = searchLdapAccount("(cn=" + cn + ")"); + assertAttribute(entry, "cn", cn); + assertAttribute(entry, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName); + return entry; + } + + protected Entry assertLdapSubAccount(String samAccountName, String cn) throws LdapException, IOException, CursorException { + Entry entry = searchLdapAccount(getSubLdapConnectionConfig(), "(cn=" + cn + ")"); + assertAttribute(entry, "cn", cn); + assertAttribute(entry, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName); + return entry; + } + + @Override + protected void assertNoLdapAccount(String uid) { + throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); + } + + protected void assertNoLdapAccount(String uid, String cn) throws LdapException, IOException, CursorException { + assertNoLdapAccount(null, uid, cn); + } + + protected void assertNoLdapSubAccount(String uid, String cn) throws LdapException, IOException, CursorException { + assertNoLdapAccount(getSubLdapConnectionConfig(), uid, cn); + } + + protected void assertNoLdapAccount(UserLdapConnectionConfig config, String uid, String cn) throws LdapException, IOException, CursorException { + LdapNetworkConnection connection = ldapConnect(config); + List entriesCn = ldapSearch(config, connection, "(cn=" + cn + ")"); + List entriesSamAccountName = ldapSearch(config, connection, "(sAMAccountName=" + uid + ")"); + ldapDisconnect(connection); + + assertEquals("Unexpected number of entries for cn=" + cn + ": " + entriesCn, 0, entriesCn.size()); + assertEquals("Unexpected number of entries for sAMAccountName=" + uid + ": " + entriesSamAccountName, 0, entriesSamAccountName.size()); + } + + @Override + protected String toAccountDn(String username) { + throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); + } + + @Override + protected String toAccountDn(String username, String fullName) { + return ("CN=" + fullName + "," + getPeopleLdapSuffix()); + } + + protected String toAccountSubDn(String username, String fullName) { + return ("CN=" + fullName + "," + getPeopleLdapSubSuffix()); + } + + @Override + protected Rdn toAccountRdn(String username, String fullName) { + try { + return new Rdn(new Ava("CN", fullName)); + } catch (LdapInvalidDnException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + protected String toOrgDn(String cn) { + return "ou=" + cn + "," + getOrgsLdapSuffix(); + } + + protected String toOrgGroupDn(String groupCn, String orgName) { + return "cn=" + groupCn + "," + toOrgDn(orgName); + } + + protected Entry assertLdapOrg(String orgName) throws LdapException, IOException, CursorException { + String dn = toOrgDn(orgName); + Entry entry = getLdapEntry(dn); + assertNotNull("No entry " + dn, entry); + assertAttribute(entry, "ou", orgName); + return entry; + } + + protected Entry assertNoLdapOrg(String orgName) throws LdapException, IOException, CursorException { + String dn = toOrgDn(orgName); + Entry entry = getLdapEntry(dn); + assertNull("Unexpected org entry " + entry, entry); + return entry; + } + + protected Entry assertLdapOrgGroup(String groupCn, String orgName) throws LdapException, IOException, CursorException { + String dn = toOrgGroupDn(groupCn, orgName); + Entry entry = getLdapEntry(dn); + assertNotNull("No entry " + dn, entry); + assertAttribute(entry, "cn", groupCn); + return entry; + } + + protected Entry assertNoLdapOrgGroup(String groupCn, String orgName) throws LdapException, IOException, CursorException { + String dn = toOrgGroupDn(groupCn, orgName); + Entry entry = getLdapEntry(dn); + assertNull("Unexpected org group entry " + entry, entry); + return entry; + } + + protected void assertLdapPassword(String uid, String fullName, String password) throws LdapException, IOException, CursorException { + assertLdapPassword(null, uid, fullName, password); + } + + protected void assertLdapPassword(UserLdapConnectionConfig config, String uid, String fullName, String password) throws LdapException, IOException, CursorException { + Entry entry = getLdapAccountByCn(config, fullName); + assertLdapPassword(config, entry, password); + } + + protected void assertLdapPassword(String uid, String password) { + throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); + } + + protected ObjectQuery createSamAccountNameQuery(String samAccountName) throws SchemaException { + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter(ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName), + prismContext); + return query; + } + + @Override + protected Entry createAccountEntry(String uid, String cn, String givenName, String sn) throws LdapException { + byte[] password = encodePassword("Secret.123"); + Entry entry = new DefaultEntry(toAccountDn(uid, cn), + "objectclass", getLdapAccountObjectClass(), + ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, uid, + "cn", cn, + "givenName", givenName, + "sn", sn, + ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512", + ATTRIBUTE_UNICODE_PWD_NAME, password); + return entry; + } + + private byte[] encodePassword(String password) { + String quotedPassword = "\"" + password + "\""; + try { + return quotedPassword.getBytes("UTF-16LE"); + } catch (UnsupportedEncodingException e) { + throw new SystemException(e.getMessage(), e); + } + } + + public void assertAttribute(PrismObject shadow, String attrName, T... expectedValues) { + assertAttribute(shadow, new QName(getResourceNamespace(), attrName), expectedValues); + } + + public void assertAttribute(PrismObject shadow, QName attrQname, T... expectedValues) { + List actualValues = ShadowUtil.getAttributeValues(shadow, attrQname); + PrismAsserts.assertSets("attribute " + attrQname + " in " + shadow, actualValues, expectedValues); + } + + protected abstract void assertAccountDisabled(PrismObject shadow); + + protected abstract void assertAccountEnabled(PrismObject shadow); + +} diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapTest.java index f3f68238e84..eb9b6bde36c 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapTest.java @@ -1,1257 +1,1257 @@ -/* - * Copyright (c) 2015-2019 Evolveum and contributors - *

- * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.testing.conntest.ad; - -import static org.testng.AssertJUnit.*; - -import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS; -import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_CREDENTIALS_PASSWORD_VALUE; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.List; -import javax.xml.datatype.XMLGregorianCalendar; -import javax.xml.namespace.QName; - -import org.apache.commons.lang.StringUtils; -import org.apache.directory.api.ldap.model.cursor.CursorException; -import org.apache.directory.api.ldap.model.entry.*; -import org.apache.directory.api.ldap.model.exception.LdapException; -import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; -import org.apache.directory.api.ldap.model.name.Ava; -import org.apache.directory.api.ldap.model.name.Rdn; -import org.apache.directory.ldap.client.api.LdapNetworkConnection; -import org.testng.AssertJUnit; -import org.testng.annotations.Listeners; -import org.testng.annotations.Test; - -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismProperty; -import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.prism.delta.PropertyDelta; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.ObjectPaging; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.prism.query.OrderDirection; -import com.evolveum.midpoint.prism.util.PrismAsserts; -import com.evolveum.midpoint.prism.util.PrismTestUtil; -import com.evolveum.midpoint.prism.xml.XmlTypeConverter; -import com.evolveum.midpoint.schema.SearchResultList; -import com.evolveum.midpoint.schema.SearchResultMetadata; -import com.evolveum.midpoint.schema.constants.MidPointConstants; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.internals.InternalCounters; -import com.evolveum.midpoint.schema.processor.ResourceAttribute; -import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.util.MiscSchemaUtil; -import com.evolveum.midpoint.schema.util.ObjectQueryUtil; -import com.evolveum.midpoint.schema.util.ShadowUtil; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.test.IntegrationTestTools; -import com.evolveum.midpoint.test.util.MidPointTestConstants; -import com.evolveum.midpoint.test.util.TestUtil; -import com.evolveum.midpoint.testing.conntest.AbstractLdapSynchronizationTest; -import com.evolveum.midpoint.util.MiscUtil; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; -import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; - -/** - * @author semancik - */ -@Listeners({ com.evolveum.midpoint.tools.testng.AlphabeticalMethodInterceptor.class }) -public abstract class AbstractAdLdapTest extends AbstractLdapSynchronizationTest - implements AdTestMixin { - - protected static final File TEST_DIR = new File(MidPointTestConstants.TEST_RESOURCES_DIR, "ad-ldap"); - - protected static final File ROLE_PIRATES_FILE = new File(TEST_DIR, "role-pirate.xml"); - protected static final String ROLE_PIRATES_OID = "5dd034e8-41d2-11e5-a123-001e8c717e5b"; - - protected static final File ROLE_META_ORG_FILE = new File(TEST_DIR, "role-meta-org.xml"); - protected static final String ROLE_META_ORG_OID = "f2ad0ace-45d7-11e5-af54-001e8c717e5b"; - - protected static final String ACCOUNT_JACK_SAM_ACCOUNT_NAME = "jack"; - protected static final String ACCOUNT_JACK_FULL_NAME = "Jack Sparrow"; - protected static final String ACCOUNT_JACK_PASSWORD = "qwe.123"; - - protected static final String USER_CPTBARBOSSA_FULL_NAME = "Captain Hector Barbossa"; - - private static final String GROUP_PIRATES_NAME = "pirates"; - private static final String GROUP_MELEE_ISLAND_NAME = "Mêlée Island"; - - protected static final int NUMBER_OF_ACCOUNTS = 12; - private static final String ASSOCIATION_GROUP_NAME = "group"; - - private static final String NS_EXTENSION = "http://whatever.com/my"; - private static final QName EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME = new QName(NS_EXTENSION, "showInAdvancedViewOnly"); - - private boolean allowDuplicateSearchResults = false; - - protected String jackAccountOid; - protected String groupPiratesOid; - protected String accountBarbossaOid; - protected String orgMeleeIslandOid; - protected String groupMeleeOid; - - @Override - public String getStartSystemCommand() { - return null; - } - - @Override - public String getStopSystemCommand() { - return null; - } - - @Override - protected File getBaseDir() { - return TEST_DIR; - } - - @Override - protected String getSyncTaskOid() { - return "cd1e0ff2-0099-11e5-9e22-001e8c717e5b"; - } - - @Override - protected boolean useSsl() { - return true; - } - - @Override - protected String getLdapSuffix() { - return "DC=win,DC=evolveum,DC=com"; - } - - @Override - protected String getLdapBindDn() { - return "CN=midpoint admin1,CN=Users,DC=win,DC=evolveum,DC=com"; - } - - @Override - protected String getLdapBindPassword() { - return "mAZadlo911"; - } - - @Override - protected int getSearchSizeLimit() { - return -1; - } - - @Override - public String getPrimaryIdentifierAttributeName() { - return "objectGUID"; - } - - @Override - protected String getPeopleLdapSuffix() { - return "CN=Users," + getLdapSuffix(); - } - - @Override - protected String getGroupsLdapSuffix() { - return "CN=Users," + getLdapSuffix(); - } - - @Override - protected String getLdapAccountObjectClass() { - return "user"; - } - - @Override - protected String getLdapGroupObjectClass() { - return "group"; - } - - @Override - protected String getLdapGroupMemberAttribute() { - return "member"; - } - - private QName getAssociationGroupQName() { - return new QName(MidPointConstants.NS_RI, ASSOCIATION_GROUP_NAME); - } - - @Override - protected boolean allowDuplicateSearchResults() { - return allowDuplicateSearchResults; - } - - @Override - protected File getSyncTaskInetOrgPersonFile() { - return new File(getBaseDir(), "task-sync-user.xml"); - } - - @Override - protected boolean isGroupMemberMandatory() { - return false; - } - - protected String getLdapConnectorClassName() { - return AdTestMixin.AD_CONNECTOR_TYPE; - } - - @Override - public void initSystem(Task initTask, OperationResult initResult) throws Exception { - super.initSystem(initTask, initResult); - - binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_OBJECT_GUID_NAME); - binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_UNICODE_PWD_NAME); - - // Users - repoAddObjectFromFile(USER_BARBOSSA_FILE, initResult); - repoAddObjectFromFile(USER_GUYBRUSH_FILE, initResult); - - // Roles - repoAddObjectFromFile(ROLE_PIRATES_FILE, initResult); - repoAddObjectFromFile(ROLE_META_ORG_FILE, initResult); - - } - - @Test - @Override - public void test000Sanity() throws Exception { - super.test000Sanity(); - - assertLdapPasswordByFullName(ACCOUNT_JACK_FULL_NAME, ACCOUNT_JACK_PASSWORD); - cleanupDelete(toAccountDn(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME)); - cleanupDelete(toAccountDn(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME)); - cleanupDelete(toAccountDn(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME)); - cleanupDelete(toGroupDn(GROUP_MELEE_ISLAND_NAME)); - cleanupDelete(toGroupDn(GROUP_FOOLS_CN)); - } - - @Test - @Override - public void test020Schema() throws Exception { - accountObjectClassDefinition = assertAdResourceSchema(resource, getAccountObjectClass(), prismContext); - - assertLdapConnectorInstances(1); - } - - // test050 in subclasses - - @Test - public void test100SeachJackBySamAccountName() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = createSamAccountNameQuery(ACCOUNT_JACK_SAM_ACCOUNT_NAME); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - when(); - SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); - - // THEN - assertSuccess(result); - - assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); - - PrismObject shadow = shadows.get(0); - display("Shadow", shadow); - assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); - jackAccountOid = shadow.getOid(); - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = shadows.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(1); - } - - @Test - public void test105SeachPiratesByCn() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getGroupObjectClass(), prismContext); - ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter("cn", GROUP_PIRATES_NAME), prismContext); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - when(); - SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); - - // THEN - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); - - PrismObject shadow = shadows.get(0); - display("Shadow", shadow); - groupPiratesOid = shadow.getOid(); - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = shadows.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(1); - } - - @Test - public void test110GetJack() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - when(); - PrismObject shadow = modelService.getObject(ShadowType.class, jackAccountOid, null, task, result); - - // THEN - assertSuccess(result); - display("Shadow", shadow); - assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); - jackAccountOid = shadow.getOid(); - - IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); - - assertAttribute(shadow, "dn", "CN=Jack Sparrow,CN=Users,DC=win,DC=evolveum,DC=com"); - assertAttribute(shadow, "cn", ACCOUNT_JACK_FULL_NAME); - assertAttribute(shadow, "sn", "Sparrow"); - assertAttribute(shadow, "info", "The best pirate the world has ever seen"); - assertAttribute(shadow, "sAMAccountName", ACCOUNT_JACK_SAM_ACCOUNT_NAME); - assertAttribute(shadow, "lastLogon", 0L); - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - assertLdapConnectorInstances(1); - } - - /** - * No paging. It should return all accounts. - */ - @Test - public void test150SeachAllAccounts() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - SearchResultList> searchResultList = doSearch(query, - NUMBER_OF_ACCOUNTS, task, result); - - // TODO: why 11? should be 1 - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 9); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * Blocksize is 5, so this is in one block. - */ - @Test - public void test152SeachFirst2Accounts() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(); - paging.setMaxSize(2); - query.setPaging(paging); - - SearchResultList> searchResultList = doSearch(query, 2, task, result); - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * Blocksize is 5, so this gets more than two blocks. - */ - @Test - public void test154SeachFirst11Accounts() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(); - paging.setMaxSize(11); - query.setPaging(paging); - - SearchResultList> searchResultList = doSearch(query, 11, task, result); - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - @Test - public void test162SeachFirst2AccountsOffset0() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(); - paging.setOffset(0); - paging.setMaxSize(2); - query.setPaging(paging); - - SearchResultList> searchResultList = doSearch(query, 2, task, result); - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * Blocksize is 5, so this is in one block. - * There is offset, so VLV should be used. - * No explicit sorting. - */ - @Test - public void test172Search2AccountsOffset1() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(1, 2); - query.setPaging(paging); - - SearchResultList> searchResultList = doSearch(query, 2, task, result); - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * Blocksize is 5, so this gets more than two blocks. - * There is offset, so VLV should be used. - * No explicit sorting. - */ - @Test - public void test174SeachFirst11AccountsOffset2() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(2, 11); - query.setPaging(paging); - - allowDuplicateSearchResults = true; - - // WHEN - SearchResultList> searchResultList = doSearch(query, 11, task, result); - - // THEN - allowDuplicateSearchResults = false; - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * Blocksize is 5, so this is in one block. - * There is offset, so VLV should be used. - * Explicit sorting. - */ - @Test - public void test182Search2AccountsOffset1SortCn() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(1, 2); - paging.setOrdering(getAttributePath(resource, "cn"), OrderDirection.ASCENDING); - query.setPaging(paging); - - SearchResultList> shadows = doSearch(query, 2, task, result); - -// assertAccountShadow(shadows.get(0), "CN=Administrator,CN=Users,DC=win,DC=evolveum,DC=com"); -// assertAccountShadow(shadows.get(1), "CN=Chuck LeChuck,CN=Users,DC=win,DC=evolveum,DC=com"); - - assertAccountShadow(shadows.get(0), "CN=Chuck LeChuck,CN=Users,DC=win,DC=evolveum,DC=com"); - assertAccountShadow(shadows.get(1), "CN=Guest,CN=Users,DC=win,DC=evolveum,DC=com"); - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = shadows.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - @Test - public void test200AssignAccountBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - assignAccountToUser(USER_BARBOSSA_OID, getResourceOid(), null, task, result); - - // THEN - then(); - assertSuccess(result); - - long tsEnd = System.currentTimeMillis(); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "title", null); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getShadowModel(shadowOid); - display("Shadow (model)", shadow); - accountBarbossaOid = shadow.getOid(); - Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); - String accountBarbossaIcfUid = (String) identifiers.iterator().next().getRealValue(); - assertNotNull("No identifier in " + shadow, accountBarbossaIcfUid); - - assertEquals("Wrong ICFS UID", - formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), - accountBarbossaIcfUid); - - assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); - - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - ResourceAttribute createTimestampAttribute = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, "createTimeStamp")); - assertNotNull("No createTimestamp in " + shadow, createTimestampAttribute); - XMLGregorianCalendar createTimestamp = createTimestampAttribute.getRealValue(); - // LDAP server may be on a different host. Allow for some clock offset. - TestUtil.assertBetween("Wrong createTimestamp in " + shadow, roundTsDown(tsStart) - 120000, roundTsUp(tsEnd) + 120000, XmlTypeConverter.toMillis(createTimestamp)); - - assertLdapConnectorInstances(2); - } - - @Test - public void test210ModifyAccountBarbossaTitle() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta delta = prismContext.deltaFactory().object() - .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); - QName attrQName = new QName(MidPointConstants.NS_RI, "title"); - ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); - PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( - ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, "Captain"); - delta.addModification(attrDelta); - - // WHEN - when(); - modelService.executeChanges(MiscSchemaUtil.createCollection(delta), null, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "title", "Captain"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - assertLdapConnectorInstances(2); - } - - @Test - public void test212ModifyAccountBarbossaShowInAdvancedViewOnlyTrue() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta delta = prismContext.deltaFactory().object() - .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); - QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); - ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); - PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( - ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); - delta.addModification(attrDelta); - - // WHEN - when(); - modelService.executeChanges(MiscSchemaUtil.createCollection(delta), null, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "showInAdvancedViewOnly", "TRUE"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - assertLdapConnectorInstances(2); - } - - /** - * Modify USER, test boolean value mapping. - */ - @Test - public void test213ModifyUserBarbossaShowInAdvancedViewOnlyFalse() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta delta = prismContext.deltaFactory().object() - .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); - QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); - ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); - PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( - ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); - delta.addModification(attrDelta); - - // WHEN - when(); - modifyUserReplace(USER_BARBOSSA_OID, ItemPath.create(UserType.F_EXTENSION, EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME), - task, result, Boolean.FALSE); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "showInAdvancedViewOnly", "FALSE"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - assertLdapConnectorInstances(2); - } - - @Test - public void test220ModifyUserBarbossaPassword() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ProtectedStringType userPasswordPs = new ProtectedStringType(); - userPasswordPs.setClearValue(USER_BARBOSSA_PASSWORD_2); - - // WHEN - when(); - modifyUserReplace(USER_BARBOSSA_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "title", "Captain"); - assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_2); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - assertLdapConnectorInstances(2); - } - - /** - * MID-5242 - */ - @Test - public void test222ModifyUserBarbossaPasswordNational() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ProtectedStringType userPasswordPs = new ProtectedStringType(); - userPasswordPs.setClearValue(USER_BARBOSSA_PASSWORD_AD_1); - - // WHEN - when(); - modifyUserReplace(USER_BARBOSSA_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "title", "Captain"); - assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_AD_1); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - assertLdapConnectorInstances(2); - } - - @Test - public void test230DisableUserBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // precondition - assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_AD_1); - - // WHEN - when(); - modifyUserReplace(USER_BARBOSSA_OID, PATH_ACTIVATION_ADMINISTRATIVE_STATUS, task, result, ActivationStatusType.DISABLED); - - // THEN - then(); - assertSuccess(result); - - assertLdapConnectorInstances(2); - - PrismObject user = getUser(USER_BARBOSSA_OID); - assertAdministrativeStatus(user, ActivationStatusType.DISABLED); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); - - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - assertAccountDisabled(shadow); - - try { - assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_AD_1); - AssertJUnit.fail("Password authentication works, but it should fail"); - } catch (SecurityException e) { - // this is expected - } - - assertLdapConnectorInstances(2); - } - - @Test - public void test239EnableUserBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyUserReplace(USER_BARBOSSA_OID, PATH_ACTIVATION_ADMINISTRATIVE_STATUS, task, result, ActivationStatusType.ENABLED); - - // THEN - then(); - assertSuccess(result); - - PrismObject user = getUser(USER_BARBOSSA_OID); - assertAdministrativeStatus(user, ActivationStatusType.ENABLED); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - assertAccountEnabled(shadow); - - assertLdapConnectorInstances(2); - } - - /** - * This should create account with a group. And disabled. - */ - @Test - public void test250AssignGuybrushPirates() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - modifyUserReplace(USER_GUYBRUSH_OID, PATH_ACTIVATION_ADMINISTRATIVE_STATUS, task, result, ActivationStatusType.DISABLED); - - // WHEN - when(); - assignRole(USER_GUYBRUSH_OID, ROLE_PIRATES_OID, task, result); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - displayValue("Entry", entry); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); - - assertLdapGroupMember(entry, GROUP_PIRATES_NAME); - - PrismObject user = getUser(USER_GUYBRUSH_OID); - assertAdministrativeStatus(user, ActivationStatusType.DISABLED); - String shadowOid = getSingleLinkOid(user); - - PrismObject shadow = getObject(ShadowType.class, shadowOid); - IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); - assertAccountDisabled(shadow); - - assertLdapConnectorInstances(2); - } - - @Test - public void test255ModifyUserGuybrushPassword() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ProtectedStringType userPasswordPs = new ProtectedStringType(); - userPasswordPs.setClearValue("wanna.be.a.123"); - - // WHEN - when(); - modifyUserReplace(USER_GUYBRUSH_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); - - try { - assertLdapPasswordByFullName(USER_GUYBRUSH_FULL_NAME, "wanna.be.a.123"); - AssertJUnit.fail("Password authentication works, but it should fail"); - } catch (SecurityException e) { - // this is expected, account is disabled - } - - assertLdapConnectorInstances(2); - } - - @Test - public void test260EnableGyubrush() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyUserReplace(USER_GUYBRUSH_OID, PATH_ACTIVATION_ADMINISTRATIVE_STATUS, task, result, ActivationStatusType.ENABLED); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - PrismObject user = getUser(USER_GUYBRUSH_OID); - assertAdministrativeStatus(user, ActivationStatusType.ENABLED); - - Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - assertAccountEnabled(shadow); - - assertLdapPasswordByFullName(USER_GUYBRUSH_FULL_NAME, "wanna.be.a.123"); - - assertLdapConnectorInstances(2); - } - - @Test - public void test300AssignBarbossaPirates() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - assignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - displayValue("Entry", entry); - assertAttribute(entry, "title", "Captain"); - - assertLdapGroupMember(entry, GROUP_PIRATES_NAME); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - PrismObject shadow = getObject(ShadowType.class, shadowOid); - IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); - - assertLdapConnectorInstances(2); - } - - @Test - public void test390ModifyUserBarbossaRename() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta objectDelta = createModifyUserReplaceDelta(USER_BARBOSSA_OID, UserType.F_NAME, - PrismTestUtil.createPolyString(USER_CPTBARBOSSA_USERNAME)); - objectDelta.addModificationReplaceProperty(UserType.F_FULL_NAME, - PrismTestUtil.createPolyString(USER_CPTBARBOSSA_FULL_NAME)); - Collection> deltas = MiscSchemaUtil.createCollection(objectDelta); - - // WHEN - when(); - modelService.executeChanges(deltas, null, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); - assertAttribute(entry, "title", "Captain"); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - display("Shadow after rename (model)", shadow); - - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, shadowOid, null, result); - display("Shadow after rename (repo)", repoShadow); - - assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - - assertLdapConnectorInstances(2); - } - - // TODO: create account with a group membership - - @Test - public void test395UnAssignBarbossaPirates() throws Exception { - // TODO: do this on another account. There is a bad interference with rename. - - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - unassignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); - displayValue("Entry", entry); - assertAttribute(entry, "title", "Captain"); - - assertLdapNoGroupMember(entry, GROUP_PIRATES_NAME); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - PrismObject shadow = getObject(ShadowType.class, shadowOid); - IntegrationTestTools.assertNoAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); - - assertLdapConnectorInstances(2); - } - - @Test - public void test399UnAssignAccountBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - unassignAccountFromUser(USER_BARBOSSA_OID, getResourceOid(), null, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertNoLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); - - PrismObject user = getUser(USER_BARBOSSA_OID); - assertNoLinkedAccount(user); - - assertLdapConnectorInstances(2); - } - - @Test - public void test500AddOrgMeleeIsland() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - PrismObject org = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(OrgType.class).instantiate(); - OrgType orgType = org.asObjectable(); - orgType.setName(new PolyStringType(GROUP_MELEE_ISLAND_NAME)); - AssignmentType metaroleAssignment = new AssignmentType(); - ObjectReferenceType metaroleRef = new ObjectReferenceType(); - metaroleRef.setOid(ROLE_META_ORG_OID); - metaroleRef.setType(RoleType.COMPLEX_TYPE); - metaroleAssignment.setTargetRef(metaroleRef); - orgType.getAssignment().add(metaroleAssignment); - - // WHEN - when(); - addObject(org, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - orgMeleeIslandOid = org.getOid(); - assertLdapGroup(GROUP_MELEE_ISLAND_NAME); - - org = getObject(OrgType.class, orgMeleeIslandOid); - groupMeleeOid = getSingleLinkOid(org); - PrismObject shadow = getShadowModel(groupMeleeOid); - display("Shadow (model)", shadow); - - assertLdapConnectorInstances(2); - } - - @Test - public void test510AssignGuybrushMeleeIsland() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - assignOrg(USER_GUYBRUSH_OID, orgMeleeIslandOid, task, result); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - - PrismObject user = getUser(USER_GUYBRUSH_OID); - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getShadowModel(shadowOid); - display("Shadow (model)", shadow); - - assertLdapGroupMember(entry, GROUP_MELEE_ISLAND_NAME); - - IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupMeleeOid); - - assertLdapConnectorInstances(2); - } - - @Override - protected void doAdditionalRenameModifications(LdapNetworkConnection connection) throws LdapException { - Modification mod = new DefaultModification(ModificationOperation.REPLACE_ATTRIBUTE, - ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, ACCOUNT_HTM_UID); - connection.modify(toAccountDn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN), mod); - display("Modified " + toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN) + " " + ATTRIBUTE_SAM_ACCOUNT_NAME_NAME + - " -> " + ACCOUNT_HTM_UID + ": " + mod); - } - - @Override - protected String getAccountHtmCnAfterRename() { - return ACCOUNT_HTM_CN; - } - - @Override - protected void assertAccountShadow(PrismObject shadow, String dn) throws SchemaException { - super.assertAccountShadow(shadow, dn); - ResourceAttribute primaryIdAttr = ShadowUtil.getAttribute(shadow, getPrimaryIdentifierAttributeQName()); - assertNotNull("No primary identifier (" + getPrimaryIdentifierAttributeQName() + " in " + shadow, primaryIdAttr); - String primaryId = primaryIdAttr.getRealValue(); - assertTrue("Unexpected chars in primary ID: '" + primaryId + "'", primaryId.matches("[a-z0-9\\-]+")); - } - - @Override - protected Entry assertLdapAccount(String samAccountName, String cn) throws LdapException, IOException, CursorException { - Entry entry = searchLdapAccount("(cn=" + cn + ")"); - assertAttribute(entry, "cn", cn); - assertAttribute(entry, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName); - return entry; - } - - @Override - protected void assertNoLdapAccount(String uid) { - throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); - } - - protected void assertNoLdapAccount(String uid, String cn) throws LdapException, IOException, CursorException { - LdapNetworkConnection connection = ldapConnect(); - List entriesCn = ldapSearch(connection, "(cn=" + cn + ")"); - List entriesSamAccountName = ldapSearch(connection, "(sAMAccountName=" + uid + ")"); - ldapDisconnect(connection); - - assertEquals("Unexpected number of entries for cn=" + cn + ": " + entriesCn, 0, entriesCn.size()); - assertEquals("Unexpected number of entries for sAMAccountName=" + uid + ": " + entriesSamAccountName, 0, entriesSamAccountName.size()); - } - - @Override - protected String toAccountDn(String username) { - throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); - } - - @Override - protected String toAccountDn(String username, String fullName) { - return "CN=" + fullName + "," + getPeopleLdapSuffix(); - } - - @Override - protected Rdn toAccountRdn(String username, String fullName) { - try { - return new Rdn(new Ava("CN", fullName)); - } catch (LdapInvalidDnException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - protected void assertLdapPasswordByFullName(String fullName, String password) - throws LdapException, IOException, CursorException { - Entry entry = getLdapAccountByCn(fullName); - assertLdapPassword(entry, password); - } - - protected void assertLdapPassword(String uid, String password) { - throw new UnsupportedOperationException( - "Boom! Cannot do this here. This is bloody AD! We need full name!"); - } - - protected ObjectQuery createSamAccountNameQuery(String samAccountName) throws SchemaException { - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter(ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName), - prismContext); - return query; - } - - @Override - protected Entry createAccountEntry(String uid, String cn, String givenName, String sn) throws LdapException { - byte[] password = encodePassword("Secret.123"); - Entry entry = new DefaultEntry(toAccountDn(uid, cn), - "objectclass", getLdapAccountObjectClass(), - ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, uid, - "cn", cn, - "givenName", givenName, - "sn", sn, - ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512", - ATTRIBUTE_UNICODE_PWD_NAME, password); - return entry; - } - - private byte[] encodePassword(String password) { - String quotedPassword = "\"" + password + "\""; - return quotedPassword.getBytes(StandardCharsets.UTF_16LE); - } - - @Override - protected void assertStepSyncToken(String syncTaskOid, int step, long tsStart, long tsEnd) - throws ObjectNotFoundException, SchemaException { - OperationResult result = createOperationResult("assertStepSyncToken"); - Task task = taskManager.getTaskPlain(syncTaskOid, result); - PrismProperty syncTokenProperty = task.getExtensionPropertyOrClone(SchemaConstants.SYNC_TOKEN); - assertNotNull("No sync token", syncTokenProperty); - assertNotNull("No sync token value", syncTokenProperty.getRealValue()); - assertNotNull("Empty sync token value", StringUtils.isBlank(syncTokenProperty.getRealValue())); - result.computeStatus(); - TestUtil.assertSuccess(result); - } - - public void assertAttribute(PrismObject shadow, String attrName, T... expectedValues) { - assertAttribute(shadow, new QName(getResourceNamespace(), attrName), expectedValues); - } - - public void assertAttribute(PrismObject shadow, QName attrQname, T... expectedValues) { - List actualValues = ShadowUtil.getAttributeValues(shadow, attrQname); - PrismAsserts.assertSets("attribute " + attrQname + " in " + shadow, actualValues, expectedValues); - } - - protected abstract void assertAccountDisabled(PrismObject shadow); - - protected abstract void assertAccountEnabled(PrismObject shadow); -} +/* + * Copyright (c) 2015-2019 Evolveum and contributors + *

+ * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.testing.conntest.ad; + +import static org.testng.AssertJUnit.*; + +import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS; +import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_CREDENTIALS_PASSWORD_VALUE; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.List; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; + +import org.apache.commons.lang3.StringUtils; +import org.apache.directory.api.ldap.model.cursor.CursorException; +import org.apache.directory.api.ldap.model.entry.*; +import org.apache.directory.api.ldap.model.exception.LdapException; +import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; +import org.apache.directory.api.ldap.model.name.Ava; +import org.apache.directory.api.ldap.model.name.Rdn; +import org.apache.directory.ldap.client.api.LdapNetworkConnection; +import org.testng.AssertJUnit; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; + +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismProperty; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.delta.PropertyDelta; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.ObjectPaging; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.OrderDirection; +import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.prism.util.PrismTestUtil; +import com.evolveum.midpoint.prism.xml.XmlTypeConverter; +import com.evolveum.midpoint.schema.SearchResultList; +import com.evolveum.midpoint.schema.SearchResultMetadata; +import com.evolveum.midpoint.schema.constants.MidPointConstants; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.internals.InternalCounters; +import com.evolveum.midpoint.schema.processor.ResourceAttribute; +import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.MiscSchemaUtil; +import com.evolveum.midpoint.schema.util.ObjectQueryUtil; +import com.evolveum.midpoint.schema.util.ShadowUtil; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.test.IntegrationTestTools; +import com.evolveum.midpoint.test.util.MidPointTestConstants; +import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.testing.conntest.AbstractLdapSynchronizationTest; +import com.evolveum.midpoint.util.MiscUtil; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; +import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; + +/** + * @author semancik + */ +@Listeners({ com.evolveum.midpoint.tools.testng.AlphabeticalMethodInterceptor.class }) +public abstract class AbstractAdLdapTest extends AbstractLdapSynchronizationTest + implements AdTestMixin { + + protected static final File TEST_DIR = new File(MidPointTestConstants.TEST_RESOURCES_DIR, "ad-ldap"); + + protected static final File ROLE_PIRATES_FILE = new File(TEST_DIR, "role-pirate.xml"); + protected static final String ROLE_PIRATES_OID = "5dd034e8-41d2-11e5-a123-001e8c717e5b"; + + protected static final File ROLE_META_ORG_FILE = new File(TEST_DIR, "role-meta-org.xml"); + protected static final String ROLE_META_ORG_OID = "f2ad0ace-45d7-11e5-af54-001e8c717e5b"; + + protected static final String ACCOUNT_JACK_SAM_ACCOUNT_NAME = "jack"; + protected static final String ACCOUNT_JACK_FULL_NAME = "Jack Sparrow"; + protected static final String ACCOUNT_JACK_PASSWORD = "qwe.123"; + + protected static final String USER_CPTBARBOSSA_FULL_NAME = "Captain Hector Barbossa"; + + private static final String GROUP_PIRATES_NAME = "pirates"; + private static final String GROUP_MELEE_ISLAND_NAME = "Mêlée Island"; + + protected static final int NUMBER_OF_ACCOUNTS = 12; + private static final String ASSOCIATION_GROUP_NAME = "group"; + + private static final String NS_EXTENSION = "http://whatever.com/my"; + private static final QName EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME = new QName(NS_EXTENSION, "showInAdvancedViewOnly"); + + private boolean allowDuplicateSearchResults = false; + + protected String jackAccountOid; + protected String groupPiratesOid; + protected String accountBarbossaOid; + protected String orgMeleeIslandOid; + protected String groupMeleeOid; + + @Override + public String getStartSystemCommand() { + return null; + } + + @Override + public String getStopSystemCommand() { + return null; + } + + @Override + protected File getBaseDir() { + return TEST_DIR; + } + + @Override + protected String getSyncTaskOid() { + return "cd1e0ff2-0099-11e5-9e22-001e8c717e5b"; + } + + @Override + protected boolean useSsl() { + return true; + } + + @Override + protected String getLdapSuffix() { + return "DC=win,DC=evolveum,DC=com"; + } + + @Override + protected String getLdapBindDn() { + return "CN=midpoint admin1,CN=Users,DC=win,DC=evolveum,DC=com"; + } + + @Override + protected String getLdapBindPassword() { + return "mAZadlo911"; + } + + @Override + protected int getSearchSizeLimit() { + return -1; + } + + @Override + public String getPrimaryIdentifierAttributeName() { + return "objectGUID"; + } + + @Override + protected String getPeopleLdapSuffix() { + return "CN=Users," + getLdapSuffix(); + } + + @Override + protected String getGroupsLdapSuffix() { + return "CN=Users," + getLdapSuffix(); + } + + @Override + protected String getLdapAccountObjectClass() { + return "user"; + } + + @Override + protected String getLdapGroupObjectClass() { + return "group"; + } + + @Override + protected String getLdapGroupMemberAttribute() { + return "member"; + } + + private QName getAssociationGroupQName() { + return new QName(MidPointConstants.NS_RI, ASSOCIATION_GROUP_NAME); + } + + @Override + protected boolean allowDuplicateSearchResults() { + return allowDuplicateSearchResults; + } + + @Override + protected File getSyncTaskInetOrgPersonFile() { + return new File(getBaseDir(), "task-sync-user.xml"); + } + + @Override + protected boolean isGroupMemberMandatory() { + return false; + } + + protected String getLdapConnectorClassName() { + return AdTestMixin.AD_CONNECTOR_TYPE; + } + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + + binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_OBJECT_GUID_NAME); + binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_UNICODE_PWD_NAME); + + // Users + repoAddObjectFromFile(USER_BARBOSSA_FILE, initResult); + repoAddObjectFromFile(USER_GUYBRUSH_FILE, initResult); + + // Roles + repoAddObjectFromFile(ROLE_PIRATES_FILE, initResult); + repoAddObjectFromFile(ROLE_META_ORG_FILE, initResult); + + } + + @Test + @Override + public void test000Sanity() throws Exception { + super.test000Sanity(); + + assertLdapPasswordByFullName(ACCOUNT_JACK_FULL_NAME, ACCOUNT_JACK_PASSWORD); + cleanupDelete(toAccountDn(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME)); + cleanupDelete(toAccountDn(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME)); + cleanupDelete(toAccountDn(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME)); + cleanupDelete(toGroupDn(GROUP_MELEE_ISLAND_NAME)); + cleanupDelete(toGroupDn(GROUP_FOOLS_CN)); + } + + @Test + @Override + public void test020Schema() throws Exception { + accountObjectClassDefinition = assertAdResourceSchema(resource, getAccountObjectClass(), prismContext); + + assertLdapConnectorInstances(1); + } + + // test050 in subclasses + + @Test + public void test100SeachJackBySamAccountName() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = createSamAccountNameQuery(ACCOUNT_JACK_SAM_ACCOUNT_NAME); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + when(); + SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); + + // THEN + assertSuccess(result); + + assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); + + PrismObject shadow = shadows.get(0); + display("Shadow", shadow); + assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); + jackAccountOid = shadow.getOid(); + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = shadows.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(1); + } + + @Test + public void test105SeachPiratesByCn() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getGroupObjectClass(), prismContext); + ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter("cn", GROUP_PIRATES_NAME), prismContext); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + when(); + SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); + + PrismObject shadow = shadows.get(0); + display("Shadow", shadow); + groupPiratesOid = shadow.getOid(); + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = shadows.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(1); + } + + @Test + public void test110GetJack() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + when(); + PrismObject shadow = modelService.getObject(ShadowType.class, jackAccountOid, null, task, result); + + // THEN + assertSuccess(result); + display("Shadow", shadow); + assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); + jackAccountOid = shadow.getOid(); + + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + + assertAttribute(shadow, "dn", "CN=Jack Sparrow,CN=Users,DC=win,DC=evolveum,DC=com"); + assertAttribute(shadow, "cn", ACCOUNT_JACK_FULL_NAME); + assertAttribute(shadow, "sn", "Sparrow"); + assertAttribute(shadow, "info", "The best pirate the world has ever seen"); + assertAttribute(shadow, "sAMAccountName", ACCOUNT_JACK_SAM_ACCOUNT_NAME); + assertAttribute(shadow, "lastLogon", 0L); + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + assertLdapConnectorInstances(1); + } + + /** + * No paging. It should return all accounts. + */ + @Test + public void test150SeachAllAccounts() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + SearchResultList> searchResultList = doSearch(query, + NUMBER_OF_ACCOUNTS, task, result); + + // TODO: why 11? should be 1 + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 9); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * Blocksize is 5, so this is in one block. + */ + @Test + public void test152SeachFirst2Accounts() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(); + paging.setMaxSize(2); + query.setPaging(paging); + + SearchResultList> searchResultList = doSearch(query, 2, task, result); + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * Blocksize is 5, so this gets more than two blocks. + */ + @Test + public void test154SeachFirst11Accounts() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(); + paging.setMaxSize(11); + query.setPaging(paging); + + SearchResultList> searchResultList = doSearch(query, 11, task, result); + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + @Test + public void test162SeachFirst2AccountsOffset0() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(); + paging.setOffset(0); + paging.setMaxSize(2); + query.setPaging(paging); + + SearchResultList> searchResultList = doSearch(query, 2, task, result); + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * Blocksize is 5, so this is in one block. + * There is offset, so VLV should be used. + * No explicit sorting. + */ + @Test + public void test172Search2AccountsOffset1() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(1, 2); + query.setPaging(paging); + + SearchResultList> searchResultList = doSearch(query, 2, task, result); + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * Blocksize is 5, so this gets more than two blocks. + * There is offset, so VLV should be used. + * No explicit sorting. + */ + @Test + public void test174SeachFirst11AccountsOffset2() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(2, 11); + query.setPaging(paging); + + allowDuplicateSearchResults = true; + + // WHEN + SearchResultList> searchResultList = doSearch(query, 11, task, result); + + // THEN + allowDuplicateSearchResults = false; + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * Blocksize is 5, so this is in one block. + * There is offset, so VLV should be used. + * Explicit sorting. + */ + @Test + public void test182Search2AccountsOffset1SortCn() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(1, 2); + paging.setOrdering(getAttributePath(resource, "cn"), OrderDirection.ASCENDING); + query.setPaging(paging); + + SearchResultList> shadows = doSearch(query, 2, task, result); + +// assertAccountShadow(shadows.get(0), "CN=Administrator,CN=Users,DC=win,DC=evolveum,DC=com"); +// assertAccountShadow(shadows.get(1), "CN=Chuck LeChuck,CN=Users,DC=win,DC=evolveum,DC=com"); + + assertAccountShadow(shadows.get(0), "CN=Chuck LeChuck,CN=Users,DC=win,DC=evolveum,DC=com"); + assertAccountShadow(shadows.get(1), "CN=Guest,CN=Users,DC=win,DC=evolveum,DC=com"); + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = shadows.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + @Test + public void test200AssignAccountBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + assignAccountToUser(USER_BARBOSSA_OID, getResourceOid(), null, task, result); + + // THEN + then(); + assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "title", null); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getShadowModel(shadowOid); + display("Shadow (model)", shadow); + accountBarbossaOid = shadow.getOid(); + Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); + String accountBarbossaIcfUid = (String) identifiers.iterator().next().getRealValue(); + assertNotNull("No identifier in " + shadow, accountBarbossaIcfUid); + + assertEquals("Wrong ICFS UID", + formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), + accountBarbossaIcfUid); + + assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); + + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + ResourceAttribute createTimestampAttribute = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, "createTimeStamp")); + assertNotNull("No createTimestamp in " + shadow, createTimestampAttribute); + XMLGregorianCalendar createTimestamp = createTimestampAttribute.getRealValue(); + // LDAP server may be on a different host. Allow for some clock offset. + TestUtil.assertBetween("Wrong createTimestamp in " + shadow, roundTsDown(tsStart) - 120000, roundTsUp(tsEnd) + 120000, XmlTypeConverter.toMillis(createTimestamp)); + + assertLdapConnectorInstances(2); + } + + @Test + public void test210ModifyAccountBarbossaTitle() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta delta = prismContext.deltaFactory().object() + .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); + QName attrQName = new QName(MidPointConstants.NS_RI, "title"); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( + ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, "Captain"); + delta.addModification(attrDelta); + + // WHEN + when(); + modelService.executeChanges(MiscSchemaUtil.createCollection(delta), null, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "title", "Captain"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertLdapConnectorInstances(2); + } + + @Test + public void test212ModifyAccountBarbossaShowInAdvancedViewOnlyTrue() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta delta = prismContext.deltaFactory().object() + .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); + QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( + ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); + delta.addModification(attrDelta); + + // WHEN + when(); + modelService.executeChanges(MiscSchemaUtil.createCollection(delta), null, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "showInAdvancedViewOnly", "TRUE"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertLdapConnectorInstances(2); + } + + /** + * Modify USER, test boolean value mapping. + */ + @Test + public void test213ModifyUserBarbossaShowInAdvancedViewOnlyFalse() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta delta = prismContext.deltaFactory().object() + .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); + QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( + ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); + delta.addModification(attrDelta); + + // WHEN + when(); + modifyUserReplace(USER_BARBOSSA_OID, ItemPath.create(UserType.F_EXTENSION, EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME), + task, result, Boolean.FALSE); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "showInAdvancedViewOnly", "FALSE"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertLdapConnectorInstances(2); + } + + @Test + public void test220ModifyUserBarbossaPassword() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ProtectedStringType userPasswordPs = new ProtectedStringType(); + userPasswordPs.setClearValue(USER_BARBOSSA_PASSWORD_2); + + // WHEN + when(); + modifyUserReplace(USER_BARBOSSA_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "title", "Captain"); + assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_2); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertLdapConnectorInstances(2); + } + + /** + * MID-5242 + */ + @Test + public void test222ModifyUserBarbossaPasswordNational() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ProtectedStringType userPasswordPs = new ProtectedStringType(); + userPasswordPs.setClearValue(USER_BARBOSSA_PASSWORD_AD_1); + + // WHEN + when(); + modifyUserReplace(USER_BARBOSSA_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "title", "Captain"); + assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_AD_1); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertLdapConnectorInstances(2); + } + + @Test + public void test230DisableUserBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // precondition + assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_AD_1); + + // WHEN + when(); + modifyUserReplace(USER_BARBOSSA_OID, PATH_ACTIVATION_ADMINISTRATIVE_STATUS, task, result, ActivationStatusType.DISABLED); + + // THEN + then(); + assertSuccess(result); + + assertLdapConnectorInstances(2); + + PrismObject user = getUser(USER_BARBOSSA_OID); + assertAdministrativeStatus(user, ActivationStatusType.DISABLED); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountDisabled(shadow); + + try { + assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_AD_1); + AssertJUnit.fail("Password authentication works, but it should fail"); + } catch (SecurityException e) { + // this is expected + } + + assertLdapConnectorInstances(2); + } + + @Test + public void test239EnableUserBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyUserReplace(USER_BARBOSSA_OID, PATH_ACTIVATION_ADMINISTRATIVE_STATUS, task, result, ActivationStatusType.ENABLED); + + // THEN + then(); + assertSuccess(result); + + PrismObject user = getUser(USER_BARBOSSA_OID); + assertAdministrativeStatus(user, ActivationStatusType.ENABLED); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountEnabled(shadow); + + assertLdapConnectorInstances(2); + } + + /** + * This should create account with a group. And disabled. + */ + @Test + public void test250AssignGuybrushPirates() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + modifyUserReplace(USER_GUYBRUSH_OID, PATH_ACTIVATION_ADMINISTRATIVE_STATUS, task, result, ActivationStatusType.DISABLED); + + // WHEN + when(); + assignRole(USER_GUYBRUSH_OID, ROLE_PIRATES_OID, task, result); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + displayValue("Entry", entry); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); + + assertLdapGroupMember(entry, GROUP_PIRATES_NAME); + + PrismObject user = getUser(USER_GUYBRUSH_OID); + assertAdministrativeStatus(user, ActivationStatusType.DISABLED); + String shadowOid = getSingleLinkOid(user); + + PrismObject shadow = getObject(ShadowType.class, shadowOid); + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + assertAccountDisabled(shadow); + + assertLdapConnectorInstances(2); + } + + @Test + public void test255ModifyUserGuybrushPassword() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ProtectedStringType userPasswordPs = new ProtectedStringType(); + userPasswordPs.setClearValue("wanna.be.a.123"); + + // WHEN + when(); + modifyUserReplace(USER_GUYBRUSH_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); + + try { + assertLdapPasswordByFullName(USER_GUYBRUSH_FULL_NAME, "wanna.be.a.123"); + AssertJUnit.fail("Password authentication works, but it should fail"); + } catch (SecurityException e) { + // this is expected, account is disabled + } + + assertLdapConnectorInstances(2); + } + + @Test + public void test260EnableGyubrush() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyUserReplace(USER_GUYBRUSH_OID, PATH_ACTIVATION_ADMINISTRATIVE_STATUS, task, result, ActivationStatusType.ENABLED); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + PrismObject user = getUser(USER_GUYBRUSH_OID); + assertAdministrativeStatus(user, ActivationStatusType.ENABLED); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountEnabled(shadow); + + assertLdapPasswordByFullName(USER_GUYBRUSH_FULL_NAME, "wanna.be.a.123"); + + assertLdapConnectorInstances(2); + } + + @Test + public void test300AssignBarbossaPirates() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + assignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + displayValue("Entry", entry); + assertAttribute(entry, "title", "Captain"); + + assertLdapGroupMember(entry, GROUP_PIRATES_NAME); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + PrismObject shadow = getObject(ShadowType.class, shadowOid); + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + + assertLdapConnectorInstances(2); + } + + @Test + public void test390ModifyUserBarbossaRename() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta objectDelta = createModifyUserReplaceDelta(USER_BARBOSSA_OID, UserType.F_NAME, + PrismTestUtil.createPolyString(USER_CPTBARBOSSA_USERNAME)); + objectDelta.addModificationReplaceProperty(UserType.F_FULL_NAME, + PrismTestUtil.createPolyString(USER_CPTBARBOSSA_FULL_NAME)); + Collection> deltas = MiscSchemaUtil.createCollection(objectDelta); + + // WHEN + when(); + modelService.executeChanges(deltas, null, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); + assertAttribute(entry, "title", "Captain"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + display("Shadow after rename (model)", shadow); + + PrismObject repoShadow = repositoryService.getObject(ShadowType.class, shadowOid, null, result); + display("Shadow after rename (repo)", repoShadow); + + assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + + assertLdapConnectorInstances(2); + } + + // TODO: create account with a group membership + + @Test + public void test395UnAssignBarbossaPirates() throws Exception { + // TODO: do this on another account. There is a bad interference with rename. + + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + unassignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); + displayValue("Entry", entry); + assertAttribute(entry, "title", "Captain"); + + assertLdapNoGroupMember(entry, GROUP_PIRATES_NAME); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + PrismObject shadow = getObject(ShadowType.class, shadowOid); + IntegrationTestTools.assertNoAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + + assertLdapConnectorInstances(2); + } + + @Test + public void test399UnAssignAccountBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + unassignAccountFromUser(USER_BARBOSSA_OID, getResourceOid(), null, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertNoLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); + + PrismObject user = getUser(USER_BARBOSSA_OID); + assertNoLinkedAccount(user); + + assertLdapConnectorInstances(2); + } + + @Test + public void test500AddOrgMeleeIsland() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + PrismObject org = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(OrgType.class).instantiate(); + OrgType orgType = org.asObjectable(); + orgType.setName(new PolyStringType(GROUP_MELEE_ISLAND_NAME)); + AssignmentType metaroleAssignment = new AssignmentType(); + ObjectReferenceType metaroleRef = new ObjectReferenceType(); + metaroleRef.setOid(ROLE_META_ORG_OID); + metaroleRef.setType(RoleType.COMPLEX_TYPE); + metaroleAssignment.setTargetRef(metaroleRef); + orgType.getAssignment().add(metaroleAssignment); + + // WHEN + when(); + addObject(org, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + orgMeleeIslandOid = org.getOid(); + assertLdapGroup(GROUP_MELEE_ISLAND_NAME); + + org = getObject(OrgType.class, orgMeleeIslandOid); + groupMeleeOid = getSingleLinkOid(org); + PrismObject shadow = getShadowModel(groupMeleeOid); + display("Shadow (model)", shadow); + + assertLdapConnectorInstances(2); + } + + @Test + public void test510AssignGuybrushMeleeIsland() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + assignOrg(USER_GUYBRUSH_OID, orgMeleeIslandOid, task, result); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + + PrismObject user = getUser(USER_GUYBRUSH_OID); + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getShadowModel(shadowOid); + display("Shadow (model)", shadow); + + assertLdapGroupMember(entry, GROUP_MELEE_ISLAND_NAME); + + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupMeleeOid); + + assertLdapConnectorInstances(2); + } + + @Override + protected void doAdditionalRenameModifications(LdapNetworkConnection connection) throws LdapException { + Modification mod = new DefaultModification(ModificationOperation.REPLACE_ATTRIBUTE, + ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, ACCOUNT_HTM_UID); + connection.modify(toAccountDn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN), mod); + display("Modified " + toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN) + " " + ATTRIBUTE_SAM_ACCOUNT_NAME_NAME + + " -> " + ACCOUNT_HTM_UID + ": " + mod); + } + + @Override + protected String getAccountHtmCnAfterRename() { + return ACCOUNT_HTM_CN; + } + + @Override + protected void assertAccountShadow(PrismObject shadow, String dn) throws SchemaException { + super.assertAccountShadow(shadow, dn); + ResourceAttribute primaryIdAttr = ShadowUtil.getAttribute(shadow, getPrimaryIdentifierAttributeQName()); + assertNotNull("No primary identifier (" + getPrimaryIdentifierAttributeQName() + " in " + shadow, primaryIdAttr); + String primaryId = primaryIdAttr.getRealValue(); + assertTrue("Unexpected chars in primary ID: '" + primaryId + "'", primaryId.matches("[a-z0-9\\-]+")); + } + + @Override + protected Entry assertLdapAccount(String samAccountName, String cn) throws LdapException, IOException, CursorException { + Entry entry = searchLdapAccount("(cn=" + cn + ")"); + assertAttribute(entry, "cn", cn); + assertAttribute(entry, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName); + return entry; + } + + @Override + protected void assertNoLdapAccount(String uid) { + throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); + } + + protected void assertNoLdapAccount(String uid, String cn) throws LdapException, IOException, CursorException { + LdapNetworkConnection connection = ldapConnect(); + List entriesCn = ldapSearch(connection, "(cn=" + cn + ")"); + List entriesSamAccountName = ldapSearch(connection, "(sAMAccountName=" + uid + ")"); + ldapDisconnect(connection); + + assertEquals("Unexpected number of entries for cn=" + cn + ": " + entriesCn, 0, entriesCn.size()); + assertEquals("Unexpected number of entries for sAMAccountName=" + uid + ": " + entriesSamAccountName, 0, entriesSamAccountName.size()); + } + + @Override + protected String toAccountDn(String username) { + throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); + } + + @Override + protected String toAccountDn(String username, String fullName) { + return "CN=" + fullName + "," + getPeopleLdapSuffix(); + } + + @Override + protected Rdn toAccountRdn(String username, String fullName) { + try { + return new Rdn(new Ava("CN", fullName)); + } catch (LdapInvalidDnException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + protected void assertLdapPasswordByFullName(String fullName, String password) + throws LdapException, IOException, CursorException { + Entry entry = getLdapAccountByCn(fullName); + assertLdapPassword(entry, password); + } + + protected void assertLdapPassword(String uid, String password) { + throw new UnsupportedOperationException( + "Boom! Cannot do this here. This is bloody AD! We need full name!"); + } + + protected ObjectQuery createSamAccountNameQuery(String samAccountName) throws SchemaException { + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter(ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName), + prismContext); + return query; + } + + @Override + protected Entry createAccountEntry(String uid, String cn, String givenName, String sn) throws LdapException { + byte[] password = encodePassword("Secret.123"); + Entry entry = new DefaultEntry(toAccountDn(uid, cn), + "objectclass", getLdapAccountObjectClass(), + ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, uid, + "cn", cn, + "givenName", givenName, + "sn", sn, + ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512", + ATTRIBUTE_UNICODE_PWD_NAME, password); + return entry; + } + + private byte[] encodePassword(String password) { + String quotedPassword = "\"" + password + "\""; + return quotedPassword.getBytes(StandardCharsets.UTF_16LE); + } + + @Override + protected void assertStepSyncToken(String syncTaskOid, int step, long tsStart, long tsEnd) + throws ObjectNotFoundException, SchemaException { + OperationResult result = createOperationResult("assertStepSyncToken"); + Task task = taskManager.getTaskPlain(syncTaskOid, result); + PrismProperty syncTokenProperty = task.getExtensionPropertyOrClone(SchemaConstants.SYNC_TOKEN); + assertNotNull("No sync token", syncTokenProperty); + assertNotNull("No sync token value", syncTokenProperty.getRealValue()); + assertNotNull("Empty sync token value", StringUtils.isBlank(syncTokenProperty.getRealValue())); + result.computeStatus(); + TestUtil.assertSuccess(result); + } + + public void assertAttribute(PrismObject shadow, String attrName, T... expectedValues) { + assertAttribute(shadow, new QName(getResourceNamespace(), attrName), expectedValues); + } + + public void assertAttribute(PrismObject shadow, QName attrQname, T... expectedValues) { + List actualValues = ShadowUtil.getAttributeValues(shadow, attrQname); + PrismAsserts.assertSets("attribute " + attrQname + " in " + shadow, actualValues, expectedValues); + } + + protected abstract void assertAccountDisabled(PrismObject shadow); + + protected abstract void assertAccountEnabled(PrismObject shadow); +} diff --git a/testing/longtest/pom.xml b/testing/longtest/pom.xml index 1940bf69169..168e26fa662 100644 --- a/testing/longtest/pom.xml +++ b/testing/longtest/pom.xml @@ -119,8 +119,8 @@ - commons-lang - commons-lang + org.apache.commons + commons-lang3 commons-io diff --git a/testing/longtest/src/test/java/com/evolveum/midpoint/testing/longtest/TestGenericSynchronization.java b/testing/longtest/src/test/java/com/evolveum/midpoint/testing/longtest/TestGenericSynchronization.java index 308b5dc9d0e..cf7fa715dde 100644 --- a/testing/longtest/src/test/java/com/evolveum/midpoint/testing/longtest/TestGenericSynchronization.java +++ b/testing/longtest/src/test/java/com/evolveum/midpoint/testing/longtest/TestGenericSynchronization.java @@ -17,7 +17,7 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang3.ArrayUtils; import org.opends.server.types.Entry; import org.opends.server.types.LDIFImportConfig; import org.opends.server.util.LDIFException; diff --git a/testing/longtest/src/test/java/com/evolveum/midpoint/testing/longtest/TestLdap.java b/testing/longtest/src/test/java/com/evolveum/midpoint/testing/longtest/TestLdap.java index 3f07caa1177..f5684829105 100644 --- a/testing/longtest/src/test/java/com/evolveum/midpoint/testing/longtest/TestLdap.java +++ b/testing/longtest/src/test/java/com/evolveum/midpoint/testing/longtest/TestLdap.java @@ -6,23 +6,15 @@ */ package com.evolveum.midpoint.testing.longtest; -import static org.testng.AssertJUnit.assertEquals; -import static org.testng.AssertJUnit.assertNotNull; -import static org.testng.AssertJUnit.assertTrue; +import static org.testng.AssertJUnit.*; import java.io.File; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - +import java.util.*; import javax.xml.namespace.QName; -import com.evolveum.midpoint.prism.path.ItemName; -import org.apache.commons.lang.mutable.MutableInt; +import org.apache.commons.lang3.mutable.MutableInt; import org.opends.server.types.Entry; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; @@ -36,6 +28,7 @@ import com.evolveum.midpoint.prism.PrismContainer; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.PrismProperty; +import com.evolveum.midpoint.prism.path.ItemName; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.schema.GetOperationOptions; @@ -50,26 +43,15 @@ import com.evolveum.midpoint.test.util.TestUtil; import com.evolveum.midpoint.util.MiscUtil; import com.evolveum.midpoint.util.aspect.ProfilingDataManager; -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.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.AssignmentPolicyEnforcementType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.midpoint.util.exception.*; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; /** * Mix of various tests for issues that are difficult to replicate using dummy resources. * * @author Radovan Semancik - * */ -@ContextConfiguration(locations = {"classpath:ctx-longtest-test-main.xml"}) +@ContextConfiguration(locations = { "classpath:ctx-longtest-test-main.xml" }) @DirtiesContext(classMode = ClassMode.AFTER_CLASS) public class TestLdap extends AbstractLongTest { @@ -192,8 +174,8 @@ public void test202AssignLdapAccountToGuybrush() throws Exception { modifyUserReplace(USER_GUYBRUSH_OID, UserType.F_JPEG_PHOTO, task, result, photoIn); Collection> options = getOperationOptionsBuilder() - .item(UserType.F_JPEG_PHOTO).retrieve() - .build(); + .item(UserType.F_JPEG_PHOTO).retrieve() + .build(); PrismObject userBefore = modelService.getObject(UserType.class, USER_GUYBRUSH_OID, options, task, result); display("User before", userBefore); byte[] userJpegPhotoBefore = userBefore.asObjectable().getJpegPhoto(); @@ -245,8 +227,7 @@ public void test204AssignRolePiratesToGuybrush() throws Exception { "dn: cn=Pirates,ou=groups,dc=example,dc=com\n" + "changetype: modify\n" + "add: uniqueMember\n" + - "uniqueMember: uid=GuyBrush,ou=pEOPle,dc=EXAMPLE,dc=cOm" - ); + "uniqueMember: uid=GuyBrush,ou=pEOPle,dc=EXAMPLE,dc=cOm"); // WHEN when(); @@ -263,7 +244,6 @@ public void test204AssignRolePiratesToGuybrush() throws Exception { assertUsers(NUM_INITIAL_USERS); } - @Test public void test400RenameLeChuckConflicting() throws Exception { // GIVEN @@ -317,7 +297,7 @@ public void test800BigLdapSearch() throws Exception { @Override public boolean handle(PrismObject shadow, OperationResult parentResult) { count.increment(); - display("Found",shadow); + display("Found", shadow); return true; } }; @@ -334,7 +314,7 @@ public boolean handle(PrismObject shadow, OperationResult parentResu // THEN then(); - assertEquals("Unexpected number of search results", NUM_LDAP_ENTRIES + 8, count.getValue()); + assertEquals("Unexpected number of search results", NUM_LDAP_ENTRIES + 8, count.intValue()); assertUsers(NUM_INITIAL_USERS + 1); } @@ -361,14 +341,14 @@ public void test810BigImport() throws Exception { OperationResult subresult = result.getLastSubresult(); TestUtil.assertInProgress("importAccountsFromResource result", subresult); - waitForTaskFinish(task, true, 20000 + NUM_LDAP_ENTRIES*2000); + waitForTaskFinish(task, true, 20000 + NUM_LDAP_ENTRIES * 2000); // THEN then(); int userCount = modelService.countObjects(UserType.class, null, null, task, result); displayValue("Users", userCount); - assertEquals("Unexpected number of users", 2*NUM_LDAP_ENTRIES + 8, userCount); + assertEquals("Unexpected number of users", 2 * NUM_LDAP_ENTRIES + 8, userCount); } @Test @@ -378,12 +358,6 @@ public void test820BigReconciliation() throws Exception { Task task = getTestTask(); OperationResult result = task.getResult(); -// System.out.println("openDJController.isRunning = " + openDJController.isRunning()); -// OperationResult testResult = modelService.testResource(RESOURCE_OPENDJ_OID, task); -// System.out.println("Test resource result = " + testResult.debugDump()); - - //task.setExtensionPropertyValue(SchemaConstants.MODEL_EXTENSION_WORKER_THREADS, 2); - ResourceType resource = modelService.getObject(ResourceType.class, RESOURCE_OPENDJ_OID, null, task, result).asObjectable(); // WHEN @@ -393,17 +367,14 @@ public void test820BigReconciliation() throws Exception { // THEN then(); -// OperationResult subresult = result.getLastSubresult(); -// TestUtil.assertInProgress("reconciliation launch result", subresult); - - waitForTaskFinish(task, true, 20000 + NUM_LDAP_ENTRIES*2000); + waitForTaskFinish(task, true, 20000 + NUM_LDAP_ENTRIES * 2000); // THEN then(); int userCount = modelService.countObjects(UserType.class, null, null, task, result); displayValue("Users", userCount); - assertEquals("Unexpected number of users", 2*NUM_LDAP_ENTRIES + 8, userCount); + assertEquals("Unexpected number of users", 2 * NUM_LDAP_ENTRIES + 8, userCount); } @Test @@ -422,15 +393,13 @@ public void test900DeleteShadows() throws Exception { // THEN then(); - waitForTaskFinish(TASK_DELETE_OPENDJ_SHADOWS_OID, true, 20000 + NUM_LDAP_ENTRIES*2000); + waitForTaskFinish(TASK_DELETE_OPENDJ_SHADOWS_OID, true, 20000 + NUM_LDAP_ENTRIES * 2000); // THEN then(); assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, 0); - - PrismObject deleteTask = getTask(TASK_DELETE_OPENDJ_SHADOWS_OID); OperationResultType deleteTaskResultType = deleteTask.asObjectable().getResult(); display("Final delete task result", deleteTaskResultType); @@ -441,15 +410,15 @@ public void test900DeleteShadows() throws Exception { assertEquals(1, opExecResults.size()); OperationResult opExecResult = opExecResults.get(0); TestUtil.assertSuccess(opExecResult); - assertEquals("Wrong exec operation count", 2*NUM_LDAP_ENTRIES+8, opExecResult.getCount()); - assertTrue("Too many subresults: "+deleteTaskResult.getSubresults().size(), deleteTaskResult.getSubresults().size() < 10); + assertEquals("Wrong exec operation count", 2 * NUM_LDAP_ENTRIES + 8, opExecResult.getCount()); + assertTrue("Too many subresults: " + deleteTaskResult.getSubresults().size(), deleteTaskResult.getSubresults().size() < 10); assertOpenDjAccountShadows(0, true, task, result); - assertUsers(2*NUM_LDAP_ENTRIES + 8); + assertUsers(2 * NUM_LDAP_ENTRIES + 8); // Check that the actual accounts were NOT deleted // (This also re-creates shadows) - assertOpenDjAccountShadows(2*NUM_LDAP_ENTRIES+8, false, task, result); + assertOpenDjAccountShadows(2 * NUM_LDAP_ENTRIES + 8, false, task, result); } @Test @@ -467,13 +436,12 @@ public void test910DeleteAccounts() throws Exception { // THEN then(); - waitForTaskFinish(TASK_DELETE_OPENDJ_ACCOUNTS_OID, true, 20000 + NUM_LDAP_ENTRIES*3000); + waitForTaskFinish(TASK_DELETE_OPENDJ_ACCOUNTS_OID, true, 20000 + NUM_LDAP_ENTRIES * 3000); // THEN then(); - assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, (2*NUM_LDAP_ENTRIES)/100+2); - + assertCounterIncrement(InternalCounters.SHADOW_FETCH_OPERATION_COUNT, (2 * NUM_LDAP_ENTRIES) / 100 + 2); PrismObject deleteTask = getTask(TASK_DELETE_OPENDJ_SHADOWS_OID); OperationResultType deleteTaskResultType = deleteTask.asObjectable().getResult(); @@ -485,11 +453,11 @@ public void test910DeleteAccounts() throws Exception { assertEquals(1, opExecResults.size()); OperationResult opExecResult = opExecResults.get(0); TestUtil.assertSuccess(opExecResult); - assertEquals("Wrong exec operation count", 2*NUM_LDAP_ENTRIES + 8, opExecResult.getCount()); - assertTrue("Too many subresults: "+deleteTaskResult.getSubresults().size(), deleteTaskResult.getSubresults().size() < 10); + assertEquals("Wrong exec operation count", 2 * NUM_LDAP_ENTRIES + 8, opExecResult.getCount()); + assertTrue("Too many subresults: " + deleteTaskResult.getSubresults().size(), deleteTaskResult.getSubresults().size() < 10); assertOpenDjAccountShadows(1, true, task, result); - assertUsers(2*NUM_LDAP_ENTRIES + 8); + assertUsers(2 * NUM_LDAP_ENTRIES + 8); assertOpenDjAccountShadows(1, false, task, result); } @@ -502,7 +470,7 @@ private void assertOpenDjAccountShadows(int expected, boolean raw, Task task, Op @Override public boolean handle(PrismObject shadow, OperationResult parentResult) { count.increment(); - display("Found",shadow); + display("Found", shadow); return true; } }; @@ -511,10 +479,10 @@ public boolean handle(PrismObject shadow, OperationResult parentResu options = SelectorOptions.createCollection(GetOperationOptions.createRaw()); } modelService.searchObjectsIterative(ShadowType.class, query, handler, options, task, result); - assertEquals("Unexpected number of search results (raw="+raw+")", expected, count.getValue()); + assertEquals("Unexpected number of search results (raw=" + raw + ")", expected, count.intValue()); } private String toDn(String username) { - return "uid="+username+","+OPENDJ_PEOPLE_SUFFIX; + return "uid=" + username + "," + OPENDJ_PEOPLE_SUFFIX; } } diff --git a/testing/longtest/src/test/java/com/evolveum/midpoint/testing/longtest/TestOrgHierarchy.java b/testing/longtest/src/test/java/com/evolveum/midpoint/testing/longtest/TestOrgHierarchy.java index bb2f473517e..f7353d913ab 100644 --- a/testing/longtest/src/test/java/com/evolveum/midpoint/testing/longtest/TestOrgHierarchy.java +++ b/testing/longtest/src/test/java/com/evolveum/midpoint/testing/longtest/TestOrgHierarchy.java @@ -8,8 +8,8 @@ import java.io.File; -import org.apache.commons.lang.ArrayUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.testng.annotations.Test; diff --git a/testing/longtest/src/test/java/com/evolveum/midpoint/testing/longtest/TestRunAs.java b/testing/longtest/src/test/java/com/evolveum/midpoint/testing/longtest/TestRunAs.java index 8c896f14936..b93bf6f7987 100644 --- a/testing/longtest/src/test/java/com/evolveum/midpoint/testing/longtest/TestRunAs.java +++ b/testing/longtest/src/test/java/com/evolveum/midpoint/testing/longtest/TestRunAs.java @@ -46,7 +46,6 @@ public class TestRunAs extends AbstractLongTest { private static final String RESOURCE_DUMMY_OID = "2f454e92-c9e8-11e7-8f60-17bc95e695f8"; protected static final File USER_ROBOT_FILE = new File(TEST_DIR, "user-robot.xml"); - protected static final String USER_ROBOT_OID = "20b4d7c0-c9e9-11e7-887c-7fe1dc65a3ed"; protected static final String USER_ROBOT_USERNAME = "robot"; protected static final File USER_TEMPLATE_PLAIN_FILE = new File(TEST_DIR, "user-template-plain.xml"); @@ -60,6 +59,9 @@ public class TestRunAs extends AbstractLongTest { private static final int NUM_ORG_MAPPINGS = 10; private static final int WARM_UP_ROUNDS = 30; + // fixed time added to the baseline before any % comparison as random stuff like GC can happen + private static final long BASELINE_RUN_TIME_TOLERANCE = 40; + private long baselineRunTime; private long baselineRepoReadCountIncrement; @@ -207,7 +209,7 @@ public void test210BarbossaSetOrganizationPlain() throws Exception { long readCountIncremenet = getCounterIncrement(InternalCounters.REPOSITORY_READ_COUNT); display("Run time " + (endMillis - starMillis) + "ms, repo read count increment " + readCountIncremenet); - baselineRunTime = endMillis - starMillis; + baselineRunTime = endMillis - starMillis + BASELINE_RUN_TIME_TOLERANCE; baselineRepoReadCountIncrement = readCountIncremenet; PrismObject userAfter = getUser(USER_BARBOSSA_OID); @@ -283,7 +285,7 @@ public void test310BarbossaSetOrganizationRunAs() throws Exception { if (readCountIncrease > 2) { fail("High increase over repo read count baseline: " + readCountIncrease + " (expected: at most 2)"); } - if (percentRuntimeIncrease > 20) { + if (percentRuntimeIncrease > 40) { fail("Too high run time increase over baseline: " + percentRuntimeIncrease + "% " + baselineRunTime + "ms -> " + runTimeMillis + "ms"); } diff --git a/testing/pom.xml b/testing/pom.xml index fc4f8e00dd1..744e5ace8e0 100644 --- a/testing/pom.xml +++ b/testing/pom.xml @@ -22,7 +22,6 @@ midPoint Testing Infrastructure - sanity - - - 4.0.0 - - - testing - com.evolveum.midpoint.testing - 4.2-SNAPSHOT - - - sanity - - midPoint Testing - Sanity - - - - com.evolveum.midpoint.infra - util - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.infra - prism-api - 4.2-SNAPSHOT - - - com.evolveum.midpoint.infra - prism-impl - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.infra - schema - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.infra - common - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.repo - repo-api - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.repo - task-api - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.model - model-api - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.model - model-impl - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.model - model-test - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.provisioning - provisioning-api - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.provisioning - provisioning-impl - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.repo - task-quartz-impl - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.repo - audit-impl - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.repo - security-impl - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.repo - security-enforcer-impl - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.repo - repo-test-util - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.model - report-impl - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.model - notifications-impl - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint.model - workflow-impl - 4.2-SNAPSHOT - test - - - - commons-lang - commons-lang - - - commons-io - commons-io - test - - - org.forgerock.opendj - opendj - test - - - org.springframework - spring-beans - - - javax.xml.bind - jaxb-api - test - - - javax.xml.ws - jaxws-api - - - - - org.testng - testng - test - - - com.evolveum.midpoint.tools - test-ng - test - - - com.evolveum.polygon - connector-ldap - test - - - com.evolveum.polygon - connector-databasetable - test - - - com.evolveum.midpoint.infra - test-util - test - - - com.evolveum.midpoint.repo - repo-sql-impl - 4.2-SNAPSHOT - test - - - com.evolveum.midpoint - midpoint-localization - ${project.version} - test - - - com.evolveum.midpoint.repo - repo-sql-impl-test - 4.2-SNAPSHOT - test - - - org.springframework - spring-test - test - - - com.evolveum.midpoint.repo - system-init - 4.2-SNAPSHOT - test - - - javax.servlet - javax.servlet-api - test - - - org.springframework - spring-aspects - test - - - org.springframework - spring-aop - test - - - - - - - maven-surefire-plugin - - - true - - - - maven-failsafe-plugin - - alphabetical - - - - - diff --git a/testing/sanity/src/test/java/com/evolveum/midpoint/testing/sanity/ModelClientUtil.java b/testing/sanity/src/test/java/com/evolveum/midpoint/testing/sanity/ModelClientUtil.java deleted file mode 100644 index e1bdff5925c..00000000000 --- a/testing/sanity/src/test/java/com/evolveum/midpoint/testing/sanity/ModelClientUtil.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (c) 2010-2014 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.testing.sanity; - -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectDeltaOperationListType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.CredentialsType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectDeltaOperationType; -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.prism.xml.ns._public.types_3.ChangeTypeType; -import com.evolveum.prism.xml.ns._public.types_3.ItemPathType; -import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; -import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; -import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.Validate; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.namespace.QName; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -/** - * @author Radovan Semancik - * - */ -public class ModelClientUtil { - - // XML constants - public static final String NS_COMMON = "http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - public static final QName COMMON_PATH = new QName(NS_COMMON, "path"); - public static final QName COMMON_VALUE = new QName(NS_COMMON, "value"); - public static final QName COMMON_GIVEN_NAME = new QName(NS_COMMON, "givenName"); - public static final QName COMMON_ASSIGNMENT = new QName(NS_COMMON, "assignment"); - - public static final String NS_TYPES = "http://prism.evolveum.com/xml/ns/public/types-3"; - private static final QName TYPES_POLYSTRING_ORIG = new QName(NS_TYPES, "orig"); - public static final QName TYPES_CLEAR_VALUE = new QName(NS_TYPES, "clearValue"); - - private static final DocumentBuilder domDocumentBuilder; - - public static JAXBContext instantiateJaxbContext() throws JAXBException { - return JAXBContext.newInstance("com.evolveum.midpoint.xml.ns._public.common.api_types_3:" + - "com.evolveum.midpoint.xml.ns._public.common.common_3:" + - "com.evolveum.midpoint.xml.ns._public.common.fault_3:" + - "com.evolveum.midpoint.xml.ns._public.connector.icf_1.connector_schema_3:" + - "com.evolveum.midpoint.xml.ns._public.connector.icf_1.resource_schema_3:" + - "com.evolveum.midpoint.xml.ns._public.resource.capabilities_3:" + - "com.evolveum.prism.xml.ns._public.annotation_3:" + - "com.evolveum.prism.xml.ns._public.query_3:" + - "com.evolveum.prism.xml.ns._public.types_3:" + - "org.w3._2000._09.xmldsig:" + - "org.w3._2001._04.xmlenc"); - } - - public static Element createPathElement(String stringPath, Document doc) { - String pathDeclaration = "declare default namespace '" + NS_COMMON + "'; " + stringPath; - return createTextElement(COMMON_PATH, pathDeclaration, doc); - } - - public static ItemPathType createItemPathType(String stringPath, PrismContext prismContext) { - String pathDeclaration = "declare default namespace '" + NS_COMMON + "'; " + stringPath; - ItemPathType itemPathType = prismContext.itemPathParser().asItemPathType(pathDeclaration); - return itemPathType; - } - -// public static SearchFilterType parseSearchFilterType(String filterClauseAsXml) throws IOException, SAXException { -// Element filterClauseAsElement = parseElement(filterClauseAsXml); -// SearchFilterType searchFilterType = new SearchFilterType(); -// searchFilterType.setFilterClause(filterClauseAsElement); -// return searchFilterType; -// } - - public static PolyStringType createPolyStringType(String string, Document doc) { - PolyStringType polyStringType = new PolyStringType(); - polyStringType.setOrig(string); - return polyStringType; - } - - public static Element createTextElement(QName qname, String value, Document doc) { - Element element = doc.createElementNS(qname.getNamespaceURI(), qname.getLocalPart()); - element.setTextContent(value); - return element; - } - - public static CredentialsType createPasswordCredentials(String password) { - CredentialsType credentialsType = new CredentialsType(); - credentialsType.setPassword(createPasswordType(password)); - return credentialsType; - } - - public static PasswordType createPasswordType(String password) { - PasswordType passwordType = new PasswordType(); - passwordType.setValue(createProtectedString(password)); - return passwordType; - } - - public static ProtectedStringType createProtectedString(String clearValue) { - ProtectedStringType protectedString = new ProtectedStringType(); - protectedString.setClearValue(clearValue); - return protectedString; } - - public static JAXBElement toJaxbElement(QName name, T value) { - return new JAXBElement<>(name, (Class) value.getClass(), value); - } - - public static Document getDocumnent() { - return domDocumentBuilder.newDocument(); - } - - public static String getTypeUri(Class type) { -// QName typeQName = JAXBUtil.getTypeQName(type); -// String typeUri = QNameUtil.qNameToUri(typeQName); - String typeUri = NS_COMMON + "#" + type.getSimpleName(); - return typeUri; - } - - public static QName getTypeQName(Class type) { - QName typeQName = new QName(NS_COMMON, type.getSimpleName()); - return typeQName; - } - - public static Element parseElement(String stringXml) throws SAXException, IOException { - Document document = domDocumentBuilder.parse(IOUtils.toInputStream(stringXml, StandardCharsets.UTF_8)); - return getFirstChildElement(document); - } - - public static Element getFirstChildElement(Node parent) { - if (parent == null || parent.getChildNodes() == null) { - return null; - } - - NodeList nodes = parent.getChildNodes(); - for (int i = 0; i < nodes.getLength(); i++) { - Node child = nodes.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE) { - return (Element) child; - } - } - - return null; - } - - /** - * Retrieves OID created by model Web Service from the returned list of ObjectDeltaOperations. - * - * @param operationListType result of the model web service executeChanges call - * @param originalDelta original request used to find corresponding ObjectDeltaOperationType instance. Must be of ADD type. - * @return OID if found - * - * PRELIMINARY IMPLEMENTATION. Currently the first returned ADD delta with the same object type as original delta is returned. - */ - public static String getOidFromDeltaOperationList(ObjectDeltaOperationListType operationListType, ObjectDeltaType originalDelta) { - Validate.notNull(operationListType); - Validate.notNull(originalDelta); - if (originalDelta.getChangeType() != ChangeTypeType.ADD) { - throw new IllegalArgumentException("Original delta is not of ADD type"); - } - if (originalDelta.getObjectToAdd() == null) { - throw new IllegalArgumentException("Original delta contains no object-to-be-added"); - } - for (ObjectDeltaOperationType operationType : operationListType.getDeltaOperation()) { - ObjectDeltaType objectDeltaType = operationType.getObjectDelta(); - if (objectDeltaType.getChangeType() == ChangeTypeType.ADD && - objectDeltaType.getObjectToAdd() != null) { - ObjectType objectAdded = (ObjectType) objectDeltaType.getObjectToAdd(); - if (objectAdded.getClass().equals(originalDelta.getObjectToAdd().getClass())) { - return objectAdded.getOid(); - } - } - } - return null; - } - - static { - try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - domDocumentBuilder = factory.newDocumentBuilder(); - } catch (ParserConfigurationException ex) { - throw new IllegalStateException("Error creating XML document " + ex.getMessage()); - } - } - -} diff --git a/testing/sanity/src/test/java/com/evolveum/midpoint/testing/sanity/TestSanity.java b/testing/sanity/src/test/java/com/evolveum/midpoint/testing/sanity/TestSanity.java deleted file mode 100644 index a017567e1b8..00000000000 --- a/testing/sanity/src/test/java/com/evolveum/midpoint/testing/sanity/TestSanity.java +++ /dev/null @@ -1,3912 +0,0 @@ -/* - * Copyright (c) 2010-2017 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.testing.sanity; - -import static org.testng.AssertJUnit.*; - -import static com.evolveum.midpoint.prism.util.PrismAsserts.assertEqualsPolyString; -import static com.evolveum.midpoint.prism.util.PrismAsserts.assertParentConsistency; -import static com.evolveum.midpoint.test.IntegrationTestTools.*; - -import java.io.File; -import java.io.IOException; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.*; -import javax.xml.bind.JAXBException; -import javax.xml.namespace.QName; -import javax.xml.ws.Holder; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.Validate; -import org.opends.server.core.ModifyOperation; -import org.opends.server.protocols.internal.InternalSearchOperation; -import org.opends.server.types.ModificationType; -import org.opends.server.types.*; -import org.opends.server.util.ChangeRecordEntry; -import org.springframework.beans.factory.annotation.Autowired; -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 org.w3c.dom.Document; -import org.w3c.dom.Element; - -import com.evolveum.midpoint.common.refinery.RefinedAttributeDefinition; -import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; -import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; -import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl; -import com.evolveum.midpoint.model.test.AbstractModelIntegrationTest; -import com.evolveum.midpoint.prism.*; -import com.evolveum.midpoint.prism.crypto.EncryptionException; -import com.evolveum.midpoint.prism.delta.ChangeType; -import com.evolveum.midpoint.prism.delta.ItemDelta; -import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.prism.delta.PropertyDelta; -import com.evolveum.midpoint.prism.match.MatchingRule; -import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; -import com.evolveum.midpoint.prism.path.ItemName; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.prism.schema.SchemaRegistry; -import com.evolveum.midpoint.prism.util.PrismAsserts; -import com.evolveum.midpoint.prism.util.PrismTestUtil; -import com.evolveum.midpoint.prism.xnode.MapXNode; -import com.evolveum.midpoint.prism.xnode.XNode; -import com.evolveum.midpoint.schema.CapabilityUtil; -import com.evolveum.midpoint.schema.DeltaConvertor; -import com.evolveum.midpoint.schema.ResultHandler; -import com.evolveum.midpoint.schema.constants.ObjectTypes; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition; -import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; -import com.evolveum.midpoint.schema.processor.ResourceSchema; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.result.OperationResultStatus; -import com.evolveum.midpoint.schema.util.*; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.task.api.TaskExecutionStatus; -import com.evolveum.midpoint.test.Checker; -import com.evolveum.midpoint.test.IntegrationTestTools; -import com.evolveum.midpoint.test.ObjectChecker; -import com.evolveum.midpoint.test.ldap.OpenDJController; -import com.evolveum.midpoint.test.util.DerbyController; -import com.evolveum.midpoint.test.util.TestUtil; -import com.evolveum.midpoint.util.DOMUtil; -import com.evolveum.midpoint.util.DebugUtil; -import com.evolveum.midpoint.util.JAXBUtil; -import com.evolveum.midpoint.util.exception.*; -import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectDeltaListType; -import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectDeltaOperationListType; -import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectListType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import com.evolveum.midpoint.xml.ns._public.common.fault_3.FaultMessage; -import com.evolveum.midpoint.xml.ns._public.common.fault_3.FaultType; -import com.evolveum.midpoint.xml.ns._public.common.fault_3.ObjectAlreadyExistsFaultType; -import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.ActivationCapabilityType; -import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.CredentialsCapabilityType; -import com.evolveum.prism.xml.ns._public.query_3.QueryType; -import com.evolveum.prism.xml.ns._public.types_3.*; - -/** - * Sanity test suite. - *

- * It tests the very basic representative test cases. It does not try to be - * complete. It rather should be quick to execute and pass through the most - * representative cases. It should test all the system components except for - * GUI. Therefore the test cases are selected to pass through most of the - * components. - *

- * It is using embedded H2 repository and embedded OpenDJ instance as a testing - * resource. The repository is instantiated from the Spring context in the - * same way as all other components. OpenDJ instance is started explicitly using - * BeforeClass method. Appropriate resource definition to reach the OpenDJ - * instance is provided in the test data and is inserted in the repository as - * part of test initialization. - * - * @author Radovan Semancik - */ -@ContextConfiguration(locations = { "classpath:ctx-sanity-test-main.xml" }) -@DirtiesContext(classMode = ClassMode.AFTER_CLASS) -public class TestSanity extends AbstractModelIntegrationTest { - - private static final String REPO_DIR_NAME = "src/test/resources/repo/"; - private static final String REQUEST_DIR_NAME = "src/test/resources/request/"; - private static final File REQUEST_DIR = new File(REQUEST_DIR_NAME); - - private static final String SYSTEM_CONFIGURATION_FILENAME = REPO_DIR_NAME + "system-configuration.xml"; - private static final String SYSTEM_CONFIGURATION_OID = "00000000-0000-0000-0000-000000000001"; - - private static final String ROLE_SUPERUSER_FILENAME = REPO_DIR_NAME + "role-superuser.xml"; - private static final String ROLE_SUPERUSER_OID = "00000000-0000-0000-0000-000000000004"; - - private static final String RESOURCE_OPENDJ_FILENAME = REPO_DIR_NAME + "resource-opendj.xml"; - private static final String RESOURCE_OPENDJ_OID = "ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff"; - private static final String RESOURCE_OPENDJ_NS = "http://midpoint.evolveum.com/xml/ns/public/resource/instance/ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff"; - protected static final QName RESOURCE_OPENDJ_ACCOUNT_OBJECTCLASS = new QName(RESOURCE_OPENDJ_NS, "inetOrgPerson"); - private static final String RESOURCE_OPENDJ_PRIMARY_IDENTIFIER_LOCAL_NAME = "entryUUID"; - private static final String RESOURCE_OPENDJ_SECONDARY_IDENTIFIER_LOCAL_NAME = "dn"; - - private static final String RESOURCE_DERBY_FILENAME = REPO_DIR_NAME + "resource-derby.xml"; - private static final String RESOURCE_DERBY_OID = "ef2bc95b-76e0-59e2-86d6-999902d3abab"; - - private static final String RESOURCE_BROKEN_FILENAME = REPO_DIR_NAME + "resource-broken.xml"; - private static final String RESOURCE_BROKEN_OID = "ef2bc95b-76e0-59e2-ffff-ffffffffffff"; - - private static final String RESOURCE_DUMMY_FILENAME = REPO_DIR_NAME + "resource-dummy.xml"; - private static final String RESOURCE_DUMMY_OID = "10000000-0000-0000-0000-000000000004"; - - private static final String CONNECTOR_LDAP_NAMESPACE = "http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/com.evolveum.polygon.connector-ldap/com.evolveum.polygon.connector.ldap.LdapConnector"; - private static final String CONNECTOR_DBTABLE_NAMESPACE = "http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/com.evolveum.polygon.connector-databasetable/org.identityconnectors.databasetable.DatabaseTableConnector"; - - private static final String CONNECTOR_BROKEN_FILENAME = REPO_DIR_NAME + "connector-broken.xml"; - private static final String CONNECTOR_BROKEN_OID = "cccccccc-76e0-59e2-ffff-ffffffffffff"; - - private static final String TASK_OPENDJ_SYNC_FILENAME = REPO_DIR_NAME + "task-opendj-sync.xml"; - private static final String TASK_OPENDJ_SYNC_OID = "91919191-76e0-59e2-86d6-3d4f02d3ffff"; - - private static final String TASK_USER_RECOMPUTE_FILENAME = REPO_DIR_NAME + "task-user-recompute.xml"; - private static final String TASK_USER_RECOMPUTE_OID = "91919191-76e0-59e2-86d6-3d4f02d3aaaa"; - - private static final String TASK_OPENDJ_RECON_FILENAME = REPO_DIR_NAME + "task-opendj-reconciliation.xml"; - private static final String TASK_OPENDJ_RECON_OID = "91919191-76e0-59e2-86d6-3d4f02d30000"; - - private static final String SAMPLE_CONFIGURATION_OBJECT_FILENAME = REPO_DIR_NAME + "sample-configuration-object.xml"; - private static final String SAMPLE_CONFIGURATION_OBJECT_OID = "c0c010c0-d34d-b33f-f00d-999111111111"; - - private static final String USER_TEMPLATE_FILENAME = REPO_DIR_NAME + "user-template.xml"; - private static final String USER_TEMPLATE_OID = "c0c010c0-d34d-b33f-f00d-777111111111"; - - private static final String USER_ADMINISTRATOR_FILENAME = REPO_DIR_NAME + "user-administrator.xml"; - private static final String USER_ADMINISTRATOR_NAME = "administrator"; - private static final String USER_ADMINISTRATOR_OID = "00000000-0000-0000-0000-000000000002"; - - private static final String USER_JACK_FILENAME = REPO_DIR_NAME + "user-jack.xml"; - private static final File USER_JACK_FILE = new File(USER_JACK_FILENAME); - private static final String USER_JACK_OID = "c0c010c0-d34d-b33f-f00d-111111111111"; - private static final String USER_JACK_LDAP_UID = "jack"; - private static final String USER_JACK_LDAP_DN = "uid=" + USER_JACK_LDAP_UID - + "," + OPENDJ_PEOPLE_SUFFIX; - - private static final String USER_GUYBRUSH_FILENAME = REPO_DIR_NAME + "user-guybrush.xml"; - private static final File USER_GUYBRUSH_FILE = new File(USER_GUYBRUSH_FILENAME); - private static final String USER_GUYBRUSH_OID = "c0c010c0-d34d-b33f-f00d-111111111222"; - private static final String USER_GUYBRUSH_USERNAME = "guybrush"; - private static final String USER_GUYBRUSH_LDAP_UID = "guybrush"; - private static final String USER_GUYBRUSH_LDAP_DN = "uid=" + USER_GUYBRUSH_LDAP_UID - + "," + OPENDJ_PEOPLE_SUFFIX; - - private static final String USER_E_LINK_ACTION_FILENAME = REPO_DIR_NAME + "user-e.xml"; - private static final File USER_E_LINK_ACTION_FILE = new File(USER_E_LINK_ACTION_FILENAME); - private static final String LDIF_E_FILENAME_LINK = "src/test/resources/request/e-create.ldif"; - - private static final String ROLE_PIRATE_FILENAME = REPO_DIR_NAME + "role-pirate.xml"; - private static final String ROLE_PIRATE_OID = "12345678-d34d-b33f-f00d-987987987988"; - - private static final String ROLE_SAILOR_FILENAME = REPO_DIR_NAME + "role-sailor.xml"; - private static final String ROLE_SAILOR_OID = "12345678-d34d-b33f-f00d-987955553535"; - - private static final String ROLE_CAPTAIN_FILENAME = REPO_DIR_NAME + "role-captain.xml"; - private static final String ROLE_CAPTAIN_OID = "12345678-d34d-b33f-f00d-987987cccccc"; - - private static final String ROLE_JUDGE_FILENAME = REPO_DIR_NAME + "role-judge.xml"; - private static final String ROLE_JUDGE_OID = "12345111-1111-2222-1111-121212111111"; - - private static final String REQUEST_USER_MODIFY_ADD_ACCOUNT_OPENDJ_FILENAME = REQUEST_DIR_NAME + "user-modify-add-account.xml"; - - private static final String REQUEST_USER_MODIFY_ADD_ACCOUNT_DERBY_FILENAME = REQUEST_DIR_NAME + "user-modify-add-account-derby.xml"; - private static final String USER_JACK_DERBY_LOGIN = "jsparrow"; - - private static final String REQUEST_USER_MODIFY_FULLNAME_LOCALITY_FILENAME = REQUEST_DIR_NAME + "user-modify-fullname-locality.xml"; - private static final String REQUEST_USER_MODIFY_GIVENNAME_FILENAME = REQUEST_DIR_NAME + "user-modify-givenname.xml"; - private static final String REQUEST_USER_MODIFY_PASSWORD_FILENAME = REQUEST_DIR_NAME + "user-modify-password.xml"; - private static final String REQUEST_USER_MODIFY_ACTIVATION_DISABLE_FILENAME = REQUEST_DIR_NAME + "user-modify-activation-disable.xml"; - private static final String REQUEST_USER_MODIFY_ACTIVATION_ENABLE_FILENAME = REQUEST_DIR_NAME + "user-modify-activation-enable.xml"; - private static final String REQUEST_USER_MODIFY_NAME_FILENAME = REQUEST_DIR_NAME + "user-modify-name.xml"; - - private static final String REQUEST_USER_MODIFY_ADD_ROLE_PIRATE_FILENAME = REQUEST_DIR_NAME + "user-modify-add-role-pirate.xml"; - private static final String REQUEST_USER_MODIFY_ADD_ROLE_CAPTAIN_1_FILENAME = REQUEST_DIR_NAME + "user-modify-add-role-captain-1.xml"; - private static final String REQUEST_USER_MODIFY_ADD_ROLE_CAPTAIN_2_FILENAME = REQUEST_DIR_NAME + "user-modify-add-role-captain-2.xml"; - private static final String REQUEST_USER_MODIFY_ADD_ROLE_JUDGE_FILENAME = REQUEST_DIR_NAME + "user-modify-add-role-judge.xml"; - private static final String REQUEST_USER_MODIFY_DELETE_ROLE_PIRATE_FILENAME = REQUEST_DIR_NAME + "user-modify-delete-role-pirate.xml"; - private static final String REQUEST_USER_MODIFY_DELETE_ROLE_CAPTAIN_1_FILENAME = REQUEST_DIR_NAME + "user-modify-delete-role-captain-1.xml"; - private static final String REQUEST_USER_MODIFY_DELETE_ROLE_CAPTAIN_2_FILENAME = REQUEST_DIR_NAME + "user-modify-delete-role-captain-2.xml"; - - private static final File REQUEST_ACCOUNT_MODIFY_ATTRS_FILE = new File(REQUEST_DIR, "account-modify-attrs.xml"); - private static final File REQUEST_ACCOUNT_MODIFY_ROOM_NUMBER_FILE = new File(REQUEST_DIR, "account-modify-roomnumber.xml"); - private static final File REQUEST_ACCOUNT_MODIFY_ROOM_NUMBER_EXPLICIT_TYPE_FILE = new File(REQUEST_DIR, "account-modify-roomnumber-explicit-type.xml"); - private static final File REQUEST_ACCOUNT_MODIFY_BAD_PATH_FILE = new File(REQUEST_DIR, "account-modify-bad-path.xml"); - - private static final String LDIF_WILL_FILENAME = REQUEST_DIR_NAME + "will.ldif"; - private static final File LDIF_WILL_MODIFY_FILE = new File(REQUEST_DIR_NAME, "will-modify.ldif"); - private static final String LDIF_WILL_WITHOUT_LOCATION_FILENAME = REQUEST_DIR_NAME + "will-without-location.ldif"; - private static final String WILL_NAME = "wturner"; - - private static final String LDIF_ANGELIKA_FILENAME = REQUEST_DIR_NAME + "angelika.ldif"; - private static final String ANGELIKA_NAME = "angelika"; - - private static final String ACCOUNT_ANGELIKA_FILENAME = REQUEST_DIR_NAME + "account-angelika.xml"; - - private static final String LDIF_ELAINE_FILENAME = REQUEST_DIR_NAME + "elaine.ldif"; - private static final String ELAINE_NAME = "elaine"; - - private static final File LDIF_GIBBS_MODIFY_FILE = new File(REQUEST_DIR_NAME, "gibbs-modify.ldif"); - - private static final String LDIF_HERMAN_FILENAME = REQUEST_DIR_NAME + "herman.ldif"; - - private static final String NS_MY = "http://whatever.com/my"; - private static final ItemName MY_SHIP_STATE = new ItemName(NS_MY, "shipState"); - private static final ItemName MY_DEAD = new ItemName(NS_MY, "dead"); - - private static final long WAIT_FOR_LOOP_SLEEP_MILLIS = 1000; - - /** - * Unmarshalled resource definition to reach the embedded OpenDJ instance. - * Used for convenience - the tests method may find it handy. - */ - private static ResourceType resourceTypeOpenDjrepo; - private static ResourceType resourceDerby; - private static String accountShadowOidOpendj; - private static String accountShadowOidDerby; - private static String accountShadowOidGuybrushOpendj; - private static String accountGuybrushOpendjEntryUuuid = null; - private static String originalJacksLdapPassword; - private static String lastJacksLdapPassword = null; - - private int lastSyncToken; - - @Autowired - private MatchingRuleRegistry matchingRuleRegistry; - - // This will get called from the superclass to init the repository - // It will be called only once - public void initSystem(Task initTask, OperationResult initResult) throws Exception { - logger.trace("initSystem"); - try { - super.initSystem(initTask, initResult); - - repoAddObjectFromFile(ROLE_SUPERUSER_FILENAME, initResult); - repoAddObjectFromFile(USER_ADMINISTRATOR_FILENAME, initResult); - - // This should discover the connectors - logger.trace("initSystem: trying modelService.postInit()"); - modelService.postInit(initResult); - logger.trace("initSystem: modelService.postInit() done"); - - login(USER_ADMINISTRATOR_NAME); - - // We need to add config after calling postInit() so it will not be applied. - // we want original logging configuration from the test logback config file, not - // the one from the system config. - repoAddObjectFromFile(SYSTEM_CONFIGURATION_FILENAME, initResult); - - // Add broken connector before importing resources - repoAddObjectFromFile(CONNECTOR_BROKEN_FILENAME, initResult); - - // Need to import instead of add, so the (dynamic) connector reference - // will be resolved - // correctly - importObjectFromFile(RESOURCE_OPENDJ_FILENAME, initResult); - importObjectFromFile(RESOURCE_BROKEN_FILENAME, initResult); - - repoAddObjectFromFile(SAMPLE_CONFIGURATION_OBJECT_FILENAME, initResult); - repoAddObjectFromFile(USER_TEMPLATE_FILENAME, initResult); - repoAddObjectFromFile(ROLE_SAILOR_FILENAME, initResult); - repoAddObjectFromFile(ROLE_PIRATE_FILENAME, initResult); - repoAddObjectFromFile(ROLE_CAPTAIN_FILENAME, initResult); - repoAddObjectFromFile(ROLE_JUDGE_FILENAME, initResult); - } catch (Exception ex) { - logger.error("erro: {}", ex); - throw ex; - } - } - - /** - * Initialize embedded OpenDJ instance Note: this is not in the abstract - * superclass so individual tests may avoid starting OpenDJ. - */ - @Override - public void startResources() throws Exception { - openDJController.startCleanServer(); - derbyController.startCleanServer(); - } - - /** - * Shutdown embedded OpenDJ instance Note: this is not in the abstract - * superclass so individual tests may avoid starting OpenDJ. - */ - @AfterClass - public static void stopResources() throws Exception { - openDJController.stop(); - derbyController.stop(); - } - - /** - * Test integrity of the test setup. - * - * @throws SchemaException - * @throws ObjectNotFoundException - * @throws CommunicationException - */ - @Test - public void test000Integrity() throws Exception { - assertNotNull(modelWeb); - assertNotNull(modelService); - assertNotNull(repositoryService); - assertNotNull(taskManager); - - assertNotNull(prismContext); - SchemaRegistry schemaRegistry = prismContext.getSchemaRegistry(); - assertNotNull(schemaRegistry); - // This is defined in extra schema. So this effectively checks whether the extra schema was loaded - PrismPropertyDefinition shipStateDefinition = schemaRegistry.findPropertyDefinitionByElementName(MY_SHIP_STATE); - assertNotNull("No my:shipState definition", shipStateDefinition); - assertEquals("Wrong maxOccurs in my:shipState definition", 1, shipStateDefinition.getMaxOccurs()); - - assertNoRepoThreadLocalCache(); - - Task task = taskManager.createTaskInstance(TestSanity.class.getName() + ".test000Integrity"); - OperationResult result = task.getResult(); - - // Check if OpenDJ resource was imported correctly - - PrismObject openDjResource = repositoryService.getObject(ResourceType.class, RESOURCE_OPENDJ_OID, null, result); - display("Imported OpenDJ resource (repository)", openDjResource); - AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, openDjResource.getOid()); - - assertNoRepoThreadLocalCache(); - - String ldapConnectorOid = openDjResource.asObjectable().getConnectorRef().getOid(); - PrismObject ldapConnector = repositoryService.getObject(ConnectorType.class, ldapConnectorOid, null, result); - display("LDAP Connector: ", ldapConnector); - - // TODO: test if OpenDJ and Derby are running - - repositoryService.getObject(GenericObjectType.class, SAMPLE_CONFIGURATION_OBJECT_OID, null, result); - } - - /** - * Repeat self-test when we have all the dependencies on the classpath. - */ - @Test - public void test001SelfTests() { - // GIVEN - Task task = getTestTask(); - - // WHEN - OperationResult repositorySelfTestResult = modelDiagnosticService.repositorySelfTest(task); - - // THEN - assertSuccess("Repository self test", repositorySelfTestResult); - - // WHEN - OperationResult provisioningSelfTestResult = modelDiagnosticService.provisioningSelfTest(task); - - // THEN - display("Repository self test result", provisioningSelfTestResult); - // There may be warning about illegal key size on some platforms. As far as it is warning and not error we are OK - // the system will fall back to a interoperable key size - if (provisioningSelfTestResult.getStatus() != OperationResultStatus.SUCCESS && provisioningSelfTestResult.getStatus() != OperationResultStatus.WARNING) { - AssertJUnit.fail("Provisioning self-test failed: " + provisioningSelfTestResult); - } - } - - /** - * Test the testResource method. Expect a complete success for now. - */ - @Test - public void test001TestConnectionOpenDJ() throws Exception { - // GIVEN - try { - assertNoRepoThreadLocalCache(); - - // WHEN - OperationResultType result = modelWeb.testResource(RESOURCE_OPENDJ_OID); - - // THEN - - assertNoRepoThreadLocalCache(); - - displayJaxb("testResource result:", result, SchemaConstants.C_RESULT); - - TestUtil.assertSuccess("testResource has failed", result); - - OperationResult opResult = new OperationResult(TestSanity.class.getName() + ".test001TestConnectionOpenDJ"); - - PrismObject resourceOpenDjRepo = repositoryService.getObject(ResourceType.class, RESOURCE_OPENDJ_OID, null, opResult); - resourceTypeOpenDjrepo = resourceOpenDjRepo.asObjectable(); - - assertNoRepoThreadLocalCache(); - assertEquals(RESOURCE_OPENDJ_OID, resourceTypeOpenDjrepo.getOid()); - display("Initialized OpenDJ resource (respository)", resourceTypeOpenDjrepo); - assertNotNull("Resource schema was not generated", resourceTypeOpenDjrepo.getSchema()); - Element resourceOpenDjXsdSchemaElement = ResourceTypeUtil.getResourceXsdSchema(resourceTypeOpenDjrepo); - assertNotNull("Resource schema was not generated", resourceOpenDjXsdSchemaElement); - - PrismObject openDjResourceProvisioninig = provisioningService.getObject(ResourceType.class, RESOURCE_OPENDJ_OID, - null, null, opResult); - display("Initialized OpenDJ resource resource (provisioning)", openDjResourceProvisioninig); - - PrismObject openDjResourceModel = provisioningService.getObject(ResourceType.class, RESOURCE_OPENDJ_OID, null, null, opResult); - display("Initialized OpenDJ resource OpenDJ resource (model)", openDjResourceModel); - - checkOpenDjResource(resourceTypeOpenDjrepo, "repository"); - - System.out.println("------------------------------------------------------------------"); - displayValue("OpenDJ resource schema (repo XML)", DOMUtil.serializeDOMToString(ResourceTypeUtil.getResourceXsdSchema(resourceOpenDjRepo))); - System.out.println("------------------------------------------------------------------"); - - checkOpenDjResource(openDjResourceProvisioninig.asObjectable(), "provisioning"); - checkOpenDjResource(openDjResourceModel.asObjectable(), "model"); - // TODO: model web - } catch (Exception ex) { - logger.info("exception: " + ex); - throw ex; - } - - } - - private void checkRepoOpenDjResource() throws ObjectNotFoundException, SchemaException { - OperationResult result = new OperationResult(TestSanity.class.getName() + ".checkRepoOpenDjResource"); - PrismObject resource = repositoryService.getObject(ResourceType.class, RESOURCE_OPENDJ_OID, null, result); - checkOpenDjResource(resource.asObjectable(), "repository"); - } - - /** - * Checks if the resource is internally consistent, if it has everything it should have. - */ - private void checkOpenDjResource(ResourceType resource, String source) throws SchemaException { - assertNotNull("Resource from " + source + " is null", resource); - ObjectReferenceType connectorRefType = resource.getConnectorRef(); - assertNotNull("Resource from " + source + " has null connectorRef", connectorRefType); - assertFalse("Resource from " + source + " has no OID in connectorRef", StringUtils.isBlank(connectorRefType.getOid())); - assertNotNull("Resource from " + source + " has null description in connectorRef", connectorRefType.getDescription()); - assertNotNull("Resource from " + source + " has null filter in connectorRef", connectorRefType.getFilter()); - assertNotNull("Resource from " + source + " has null filter element in connectorRef", connectorRefType.getFilter().getFilterClauseXNode()); - assertNotNull("Resource from " + source + " has null configuration", resource.getConnectorConfiguration()); - assertNotNull("Resource from " + source + " has null schema", resource.getSchema()); - checkOpenDjSchema(resource, source); - assertNotNull("Resource from " + source + " has null schemahandling", resource.getSchemaHandling()); - checkOpenDjSchemaHandling(resource, source); - if (!source.equals("repository")) { - // This is generated on the fly in provisioning - assertNotNull("Resource from " + source + " has null nativeCapabilities", resource.getCapabilities().getNative()); - assertFalse("Resource from " + source + " has empty nativeCapabilities", - resource.getCapabilities().getNative().getAny().isEmpty()); - } - assertNotNull("Resource from " + source + " has null configured capabilities", resource.getCapabilities().getConfigured()); - assertFalse("Resource from " + source + " has empty capabilities", resource.getCapabilities().getConfigured().getAny().isEmpty()); - assertNotNull("Resource from " + source + " has null synchronization", resource.getSynchronization()); - checkOpenDjConfiguration(resource.asPrismObject(), source); - } - - private void checkOpenDjSchema(ResourceType resource, String source) throws SchemaException { - ResourceSchema schema = RefinedResourceSchemaImpl.getResourceSchema(resource, prismContext); - ObjectClassComplexTypeDefinition accountDefinition = schema.findObjectClassDefinition(RESOURCE_OPENDJ_ACCOUNT_OBJECTCLASS); - assertNotNull("Schema does not define any account (resource from " + source + ")", accountDefinition); - Collection identifiers = accountDefinition.getPrimaryIdentifiers(); - assertFalse("No account identifiers (resource from " + source + ")", identifiers == null || identifiers.isEmpty()); - // TODO: check for naming attributes and display names, etc - - ActivationCapabilityType capActivation = ResourceTypeUtil.getEffectiveCapability(resource, ActivationCapabilityType.class); - if (capActivation != null && capActivation.getStatus() != null && capActivation.getStatus().getAttribute() != null) { - // There is simulated activation capability, check if the attribute is in schema. - QName enableAttrName = capActivation.getStatus().getAttribute(); - ResourceAttributeDefinition enableAttrDef = accountDefinition.findAttributeDefinition(enableAttrName); - displayDumpable("Simulated activation attribute definition", enableAttrDef); - assertNotNull("No definition for enable attribute " + enableAttrName + " in account (resource from " + source + ")", enableAttrDef); - assertTrue("Enable attribute " + enableAttrName + " is not ignored (resource from " + source + ")", enableAttrDef.isIgnored()); - } - } - - private void checkOpenDjSchemaHandling(ResourceType resource, String source) { - SchemaHandlingType schemaHandling = resource.getSchemaHandling(); - for (ResourceObjectTypeDefinitionType resObjectTypeDef : schemaHandling.getObjectType()) { - if (resObjectTypeDef.getKind() == ShadowKindType.ACCOUNT) { - String name = resObjectTypeDef.getIntent(); - assertNotNull("Resource " + resource + " from " + source + " has an schemaHandlig account definition without intent", name); - assertNotNull("Account type " + name + " in " + resource + " from " + source + " does not have object class", resObjectTypeDef.getObjectClass()); - } - if (resObjectTypeDef.getKind() == ShadowKindType.ENTITLEMENT) { - String name = resObjectTypeDef.getIntent(); - assertNotNull("Resource " + resource + " from " + source + " has an schemaHandlig entitlement definition without intent", name); - assertNotNull("Entitlement type " + name + " in " + resource + " from " + source + " does not have object class", resObjectTypeDef.getObjectClass()); - } - } - } - - private void checkOpenDjConfiguration(PrismObject resource, String source) { - checkOpenResourceConfiguration(resource, CONNECTOR_LDAP_NAMESPACE, "bindPassword", 8, source); - } - - private void checkOpenResourceConfiguration(PrismObject resource, String connectorNamespace, String credentialsPropertyName, - int numConfigProps, String source) { - PrismContainer configurationContainer = resource.findContainer(ResourceType.F_CONNECTOR_CONFIGURATION); - assertNotNull("No configuration container in " + resource + " from " + source, configurationContainer); - PrismContainer configPropsContainer = configurationContainer.findContainer(SchemaTestConstants.ICFC_CONFIGURATION_PROPERTIES); - assertNotNull("No configuration properties container in " + resource + " from " + source, configPropsContainer); - Collection> configProps = configPropsContainer.getValue().getItems(); - assertEquals("Wrong number of config properties in " + resource + " from " + source, numConfigProps, configProps.size()); - PrismProperty credentialsProp = configPropsContainer.findProperty(new ItemName(connectorNamespace, credentialsPropertyName)); - if (credentialsProp == null) { - // The is the heisenbug we are looking for. Just dump the entire damn thing. - displayValue("Configuration with the heisenbug", configurationContainer.debugDump()); - } - assertNotNull("No " + credentialsPropertyName + " property in " + resource + " from " + source, credentialsProp); - assertEquals("Wrong number of " + credentialsPropertyName + " property value in " + resource + " from " + source, 1, credentialsProp.getValues().size()); - PrismPropertyValue credentialsPropertyValue = credentialsProp.getValues().iterator().next(); - assertNotNull("No " + credentialsPropertyName + " property value in " + resource + " from " + source, credentialsPropertyValue); - if (credentialsPropertyValue.isRaw()) { - Object rawElement = credentialsPropertyValue.getRawElement(); - assertTrue("Wrong element class " + rawElement.getClass() + " in " + resource + " from " + source, rawElement instanceof MapXNode); -// Element rawDomElement = (Element)rawElement; - MapXNode xmap = (MapXNode) rawElement; - try { - ProtectedStringType protectedType = new ProtectedStringType(); - prismContext.hacks().parseProtectedType(protectedType, xmap, prismContext, prismContext.getDefaultParsingContext()); - // display("LDAP credentials raw element", DOMUtil.serializeDOMToString(rawDomElement)); -// assertEquals("Wrong credentials element namespace in "+resource+" from "+source, connectorNamespace, rawDomElement.getNamespaceURI()); -// assertEquals("Wrong credentials element local name in "+resource+" from "+source, credentialsPropertyName, rawDomElement.getLocalName()); -// Element encryptedDataElement = DOMUtil.getChildElement(rawDomElement, new QName(DOMUtil.NS_XML_ENC, "EncryptedData")); - EncryptedDataType encryptedDataType = protectedType.getEncryptedDataType(); - assertNotNull("No EncryptedData element", encryptedDataType); - } catch (SchemaException ex) { - throw new IllegalArgumentException(ex); - } -// assertEquals("Wrong EncryptedData element namespace in "+resource+" from "+source, DOMUtil.NS_XML_ENC, encryptedDataType.getNamespaceURI()); -// assertEquals("Wrong EncryptedData element local name in "+resource+" from "+source, "EncryptedData", encryptedDataType.getLocalName()); - } else { - Object credentials = credentialsPropertyValue.getValue(); - assertTrue("Wrong type of credentials configuration property in " + resource + " from " + source + ": " + credentials.getClass(), credentials instanceof ProtectedStringType); - ProtectedStringType credentialsPs = (ProtectedStringType) credentials; - EncryptedDataType encryptedData = credentialsPs.getEncryptedDataType(); - assertNotNull("No EncryptedData element", encryptedData); - } - - } - - @Test - public void test002AddDerbyResource() throws Exception { - // GIVEN - OperationResult result = createOperationResult(); - - checkRepoOpenDjResource(); - assertNoRepoThreadLocalCache(); - - PrismObject resource = PrismTestUtil.parseObject(new File(RESOURCE_DERBY_FILENAME)); - assertParentConsistency(resource); - fillInConnectorRef(resource, IntegrationTestTools.DBTABLE_CONNECTOR_TYPE, result); - - OperationResultType resultType = new OperationResultType(); - Holder resultHolder = new Holder<>(resultType); - Holder oidHolder = new Holder<>(); - - display("Adding Derby Resource", resource); - - // WHEN - addObjectViaModelWS(resource.asObjectable(), null, oidHolder, resultHolder); - - // THEN - // Check if Derby resource was imported correctly - PrismObject derbyResource = repositoryService.getObject(ResourceType.class, RESOURCE_DERBY_OID, null, result); - AssertJUnit.assertEquals(RESOURCE_DERBY_OID, derbyResource.getOid()); - - assertNoRepoThreadLocalCache(); - - String dbConnectorOid = derbyResource.asObjectable().getConnectorRef().getOid(); - PrismObject dbConnector = repositoryService.getObject(ConnectorType.class, dbConnectorOid, null, result); - display("DB Connector: ", dbConnector); - - // Check if password was encrypted during import - // via JAXB - Object configurationPropertiesElement = JAXBUtil.findElement(derbyResource.asObjectable().getConnectorConfiguration().getAny(), - new QName(dbConnector.asObjectable().getNamespace(), "configurationProperties")); - Object passwordElement = JAXBUtil.findElement(JAXBUtil.listChildElements(configurationPropertiesElement), - new QName(dbConnector.asObjectable().getNamespace(), "password")); - System.out.println("Password element: " + passwordElement); - - // via prisms - PrismContainerValue configurationProperties = derbyResource.findContainer( - ItemPath.create( - ResourceType.F_CONNECTOR_CONFIGURATION, - new QName("configurationProperties"))) - .getValue(); - PrismProperty password = configurationProperties.findProperty(new ItemName(dbConnector.asObjectable().getNamespace(), "password")); - System.out.println("Password property: " + password); - } - - private void addObjectViaModelWS(ObjectType objectType, ModelExecuteOptionsType options, Holder oidHolder, Holder resultHolder) throws FaultMessage { - ObjectDeltaListType deltaList = new ObjectDeltaListType(); - ObjectDeltaType objectDelta = new ObjectDeltaType(); - objectDelta.setObjectToAdd(objectType); - QName type = objectType.asPrismObject().getDefinition().getTypeName(); - objectDelta.setObjectType(type); - objectDelta.setChangeType(ChangeTypeType.ADD); - deltaList.getDelta().add(objectDelta); - ObjectDeltaOperationListType objectDeltaOperationListType = modelWeb.executeChanges(deltaList, options); - ObjectDeltaOperationType objectDeltaOperationType = getOdoFromDeltaOperationList(objectDeltaOperationListType, objectDelta); - resultHolder.value = objectDeltaOperationType.getExecutionResult(); - oidHolder.value = ((ObjectType) objectDeltaOperationType.getObjectDelta().getObjectToAdd()).getOid(); - } - - // ugly hack... - private static ObjectDeltaOperationType getOdoFromDeltaOperationList(ObjectDeltaOperationListType operationListType, ObjectDeltaType originalDelta) { - Validate.notNull(operationListType); - Validate.notNull(originalDelta); - for (ObjectDeltaOperationType operationType : operationListType.getDeltaOperation()) { - ObjectDeltaType objectDeltaType = operationType.getObjectDelta(); - if (originalDelta.getChangeType() == ChangeTypeType.ADD) { - if (objectDeltaType.getChangeType() == originalDelta.getChangeType() && - objectDeltaType.getObjectToAdd() != null) { - ObjectType objectAdded = (ObjectType) objectDeltaType.getObjectToAdd(); - if (objectAdded.getClass().equals(originalDelta.getObjectToAdd().getClass())) { - return operationType; - } - } - } else { - if (objectDeltaType.getChangeType() == originalDelta.getChangeType() && - originalDelta.getOid().equals(objectDeltaType.getOid())) { - return operationType; - } - } - } - throw new IllegalStateException("No suitable ObjectDeltaOperationType found"); - } - - private void checkRepoDerbyResource() throws ObjectNotFoundException, SchemaException { - OperationResult result = new OperationResult(TestSanity.class.getName() + ".checkRepoDerbyResource"); - PrismObject resource = repositoryService.getObject(ResourceType.class, RESOURCE_DERBY_OID, null, result); - checkDerbyResource(resource, "repository"); - } - - private void checkDerbyResource(PrismObject resource, String source) { - checkDerbyConfiguration(resource, source); - } - - private void checkDerbyConfiguration(PrismObject resource, String source) { - checkOpenResourceConfiguration(resource, CONNECTOR_DBTABLE_NAMESPACE, "password", 10, source); - } - - /** - * Test the testResource method. Expect a complete success for now. - */ - @Test - public void test003TestConnectionDerby() throws Exception { - // GIVEN - - checkRepoDerbyResource(); - assertNoRepoThreadLocalCache(); - - // WHEN - OperationResultType result = modelWeb.testResource(RESOURCE_DERBY_OID); - - // THEN - - assertNoRepoThreadLocalCache(); - displayJaxb("testResource result:", result, SchemaConstants.C_RESULT); - - TestUtil.assertSuccess("testResource has failed", result.getPartialResults().get(0)); - - OperationResult opResult = new OperationResult(TestSanity.class.getName() + ".test002TestConnectionDerby"); - - PrismObject rObject = repositoryService.getObject(ResourceType.class, RESOURCE_DERBY_OID, null, opResult); - resourceDerby = rObject.asObjectable(); - checkDerbyResource(rObject, "repository(after test)"); - - assertNoRepoThreadLocalCache(); - assertEquals(RESOURCE_DERBY_OID, resourceDerby.getOid()); - display("Initialized Derby resource (respository)", resourceDerby); - assertNotNull("Resource schema was not generated", resourceDerby.getSchema()); - Element resourceDerbyXsdSchemaElement = ResourceTypeUtil.getResourceXsdSchema(resourceDerby); - assertNotNull("Resource schema was not generated", resourceDerbyXsdSchemaElement); - - PrismObject derbyResourceProvisioninig = provisioningService.getObject(ResourceType.class, RESOURCE_DERBY_OID, - null, null, opResult); - display("Initialized Derby resource (provisioning)", derbyResourceProvisioninig); - - PrismObject derbyResourceModel = provisioningService.getObject(ResourceType.class, RESOURCE_DERBY_OID, - null, null, opResult); - display("Initialized Derby resource (model)", derbyResourceModel); - - // TODO: check -// checkOpenDjResource(resourceOpenDj,"repository"); -// checkOpenDjResource(openDjResourceProvisioninig,"provisioning"); -// checkOpenDjResource(openDjResourceModel,"model"); - // TODO: model web - - } - - @Test - public void test004Capabilities() - throws ObjectNotFoundException, SchemaException, FaultMessage { - // GIVEN - - checkRepoOpenDjResource(); - - assertNoRepoThreadLocalCache(); - - Holder resultHolder = new Holder<>(); - Holder objectHolder = new Holder<>(); - SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); - - // WHEN - modelWeb.getObject(ObjectTypes.RESOURCE.getTypeQName(), RESOURCE_OPENDJ_OID, - options, objectHolder, resultHolder); - - ResourceType resource = (ResourceType) objectHolder.value; - - // THEN - display("Resource", resource); - - assertNoRepoThreadLocalCache(); - - CapabilityCollectionType nativeCapabilities = resource.getCapabilities().getNative(); - List capabilities = nativeCapabilities.getAny(); - assertFalse("Empty capabilities returned", capabilities.isEmpty()); - - for (Object capability : nativeCapabilities.getAny()) { - System.out.println("Native Capability: " + CapabilityUtil.getCapabilityDisplayName(capability) + " : " + capability); - } - - if (resource.getCapabilities() != null) { - for (Object capability : resource.getCapabilities().getConfigured().getAny()) { - System.out.println("Configured Capability: " + CapabilityUtil.getCapabilityDisplayName(capability) + " : " + capability); - } - } - - List effectiveCapabilities = ResourceTypeUtil.getEffectiveCapabilities(resource); - for (Object capability : effectiveCapabilities) { - System.out.println("Efective Capability: " + CapabilityUtil.getCapabilityDisplayName(capability) + " : " + capability); - } - - CredentialsCapabilityType capCred = CapabilityUtil.getCapability(capabilities, CredentialsCapabilityType.class); - assertNotNull("password capability not present", capCred.getPassword()); - // Connector cannot do activation, this should be null - ActivationCapabilityType capAct = CapabilityUtil.getCapability(capabilities, ActivationCapabilityType.class); - assertNull("Found activation capability while not expecting it", capAct); - - capCred = ResourceTypeUtil.getEffectiveCapability(resource, CredentialsCapabilityType.class); - assertNotNull("password capability not found", capCred.getPassword()); - // Although connector does not support activation, the resource specifies a way how to simulate it. - // Therefore the following should succeed - capAct = ResourceTypeUtil.getEffectiveCapability(resource, ActivationCapabilityType.class); - assertNotNull("activation capability not found", capAct); - - } - - @Test - public void test005resolveConnectorRef() throws Exception { - PrismObject resource = PrismTestUtil.parseObject(new File(RESOURCE_DUMMY_FILENAME)); - - ModelExecuteOptionsType options = new ModelExecuteOptionsType(); - options.setIsImport(Boolean.TRUE); - addObjectViaModelWS(resource.asObjectable(), options, new Holder<>(), new Holder<>()); - - OperationResult repoResult = new OperationResult("getObject"); - - PrismObject uObject = repositoryService.getObject(ResourceType.class, RESOURCE_DUMMY_OID, null, repoResult); - assertNotNull(uObject); - - ResourceType resourceType = uObject.asObjectable(); - assertNotNull("Reference on the connector must not be null in resource.", resourceType.getConnectorRef()); - assertNotNull("Missing oid reference on the connector", resourceType.getConnectorRef().getOid()); - - } - - @Test - public void test006reimportResourceDummy() throws Exception { - //get object from repo (with version set and try to add it - it should be re-added, without error) - OperationResult repoResult = new OperationResult("getObject"); - - PrismObject resource = repositoryService.getObject(ResourceType.class, RESOURCE_DUMMY_OID, null, repoResult); - assertNotNull(resource); - - ModelExecuteOptionsType options = new ModelExecuteOptionsType(); - options.setOverwrite(Boolean.TRUE); - options.setIsImport(Boolean.TRUE); - addObjectViaModelWS(resource.asObjectable(), options, new Holder<>(), new Holder<>()); - - //TODO: add some asserts - - //parse object from file again and try to add it - this should fail, becasue the same object already exists) - resource = PrismTestUtil.parseObject(new File(RESOURCE_DUMMY_FILENAME)); - - try { - Holder resultHolder = new Holder<>(); - options = new ModelExecuteOptionsType(); - options.setIsImport(Boolean.TRUE); - addObjectViaModelWS(resource.asObjectable(), options, new Holder<>(), - resultHolder); - - OperationResultType result = resultHolder.value; - TestUtil.assertFailure(result); - - fail("Expected object already exists exception, but haven't got one."); - } catch (FaultMessage ex) { - logger.info("fault {}", ex.getFaultInfo(), ex.getCause()); - if (ex.getFaultInfo() instanceof ObjectAlreadyExistsFaultType) { - // this is OK, we expect this - } else { - fail("Expected object already exists exception, but got: " + ex.getFaultInfo()); - } - - } - -// ResourceType resourceType = uObject.asObjectable(); -// assertNotNull("Reference on the connector must not be null in resource.",resourceType.getConnectorRef()); -// assertNotNull("Missing oid reference on the connector",resourceType.getConnectorRef().getOid()); - - } - - /** - * Attempt to add new user. It is only added to the repository, so check if - * it is in the repository after the operation. - */ - @Test - public void test010AddUser() throws Exception { - // GIVEN - checkRepoOpenDjResource(); - assertNoRepoThreadLocalCache(); - - PrismObject user = PrismTestUtil.parseObject(USER_JACK_FILE); - UserType userType = user.asObjectable(); - assertParentConsistency(user); - - // Encrypt Jack's password - protector.encrypt(userType.getCredentials().getPassword().getValue()); - assertParentConsistency(user); - - OperationResultType result = new OperationResultType(); - Holder resultHolder = new Holder<>(result); - Holder oidHolder = new Holder<>(); - - display("Adding user object", userType); - - // WHEN - addObjectViaModelWS(userType, null, oidHolder, resultHolder); - - // THEN - - assertNoRepoThreadLocalCache(); - displayJaxb("addObject result:", resultHolder.value, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("addObject has failed", resultHolder.value); - -// AssertJUnit.assertEquals(USER_JACK_OID, oid); - - OperationResult repoResult = new OperationResult("getObject"); - - PrismObject uObject = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); - UserType repoUser = uObject.asObjectable(); - - repoResult.computeStatus(); - display("repository.getObject result", repoResult); - TestUtil.assertSuccess("getObject has failed", repoResult); - AssertJUnit.assertEquals(USER_JACK_OID, repoUser.getOid()); - assertEqualsPolyString("fullName", userType.getFullName(), repoUser.getFullName()); - - // TODO: better checks - } - - /** - * Add account to user. This should result in account provisioning. Check if - * that happens in repo and in LDAP. - */ - @Test - public void test013AddOpenDjAccountToUser() throws Exception { - try { - // GIVEN - checkRepoOpenDjResource(); - assertNoRepoThreadLocalCache(); - - // IMPORTANT! SWITCHING OFF ASSIGNMENT ENFORCEMENT HERE! - setAssignmentEnforcement(AssignmentPolicyEnforcementType.NONE); - // This is not redundant. It checks that the previous command set the policy correctly - assertSyncSettingsAssignmentPolicyEnforcement(AssignmentPolicyEnforcementType.NONE); - - ObjectDeltaType objectChange = unmarshalValueFromFile( - REQUEST_USER_MODIFY_ADD_ACCOUNT_OPENDJ_FILENAME, ObjectDeltaType.class); - - // WHEN - when(); - OperationResultType result = modifyObjectViaModelWS(objectChange); - - // THEN - then(); - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("modifyObject has failed", result); - - // Check if user object was modified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - - PrismObject repoUser = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); - UserType repoUserType = repoUser.asObjectable(); - - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject has failed", repoResult); - display("User (repository)", repoUser); - - List accountRefs = repoUserType.getLinkRef(); - assertEquals("No accountRefs", 1, accountRefs.size()); - ObjectReferenceType accountRef = accountRefs.get(0); - accountShadowOidOpendj = accountRef.getOid(); - assertFalse(accountShadowOidOpendj.isEmpty()); - - // Check if shadow was created in the repo - - repoResult = new OperationResult("getObject"); - - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, - null, repoResult); - ShadowType repoShadowType = repoShadow.asObjectable(); - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject has failed", repoResult); - display("Shadow (repository)", repoShadow); - assertNotNull(repoShadowType); - assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); - - assertNotNull("Shadow stored in repository has no name", repoShadowType.getName()); - // Check the "name" property, it should be set to DN, not entryUUID - assertEquals("Wrong name property", USER_JACK_LDAP_DN.toLowerCase(), repoShadowType.getName().getOrig().toLowerCase()); - - // check attributes in the shadow: should be only identifiers (ICF UID) - String uid = checkRepoShadow(repoShadow); - - // check if account was created in LDAP - - Entry entry = openDJController.searchAndAssertByEntryUuid(uid); - - display("LDAP account", entry); - - OpenDJController.assertAttribute(entry, "uid", "jack"); - OpenDJController.assertAttribute(entry, "givenName", "Jack"); - OpenDJController.assertAttribute(entry, "sn", "Sparrow"); - OpenDJController.assertAttribute(entry, "cn", "Jack Sparrow"); - OpenDJController.assertAttribute(entry, "displayName", "Jack Sparrow"); - // The "l" attribute is assigned indirectly through schemaHandling and - // config object - OpenDJController.assertAttribute(entry, "l", "Black Pearl"); - - assertTrue("LDAP account is not enabled", openDJController.isAccountEnabled(entry)); - - originalJacksLdapPassword = OpenDJController.getAttributeValue(entry, "userPassword"); - assertNotNull("Pasword was not set on create", originalJacksLdapPassword); - System.out.println("password after create: " + originalJacksLdapPassword); - - // Use getObject to test fetch of complete shadow - - assertNoRepoThreadLocalCache(); - - Holder resultHolder = new Holder<>(); - Holder objectHolder = new Holder<>(); - SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); - - // WHEN - modelWeb.getObject(ObjectTypes.SHADOW.getTypeQName(), accountShadowOidOpendj, - options, objectHolder, resultHolder); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("getObject result", resultHolder.value, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("getObject has failed", resultHolder.value); - - ShadowType modelShadow = (ShadowType) objectHolder.value; - display("Shadow (model)", modelShadow); - - AssertJUnit.assertNotNull(modelShadow); - AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, modelShadow.getResourceRef().getOid()); - - assertAttributeNotNull(modelShadow, getOpenDjPrimaryIdentifierQName()); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "uid", "jack"); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "givenName", "Jack"); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "sn", "Sparrow"); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "cn", "Jack Sparrow"); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "displayName", "Jack Sparrow"); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "l", "Black Pearl"); - assertNull("carLicense attribute sneaked to LDAP", OpenDJController.getAttributeValue(entry, "carLicense")); - assertNull("postalAddress attribute sneaked to LDAP", OpenDJController.getAttributeValue(entry, "postalAddress")); - - assertNotNull("Activation is null (model)", modelShadow.getActivation()); - assertEquals("Wrong administrativeStatus in the shadow (model)", ActivationStatusType.ENABLED, modelShadow.getActivation().getAdministrativeStatus()); - } catch (Exception ex) { - logger.info("ERROR", ex); - throw ex; - } - - } - - private OperationResultType modifyObjectViaModelWS(ObjectDeltaType objectChange) throws FaultMessage { - ObjectDeltaListType deltaList = new ObjectDeltaListType(); - deltaList.getDelta().add(objectChange); - ObjectDeltaOperationListType list = modelWeb.executeChanges(deltaList, null); - return getOdoFromDeltaOperationList(list, objectChange).getExecutionResult(); - } - - /** - * Add Derby account to user. This should result in account provisioning. Check if - * that happens in repo and in Derby. - */ - @Test - public void test014AddDerbyAccountToUser() throws IOException, JAXBException, FaultMessage, - ObjectNotFoundException, SchemaException, SQLException { - // GIVEN - - checkRepoDerbyResource(); - assertNoRepoThreadLocalCache(); - - ObjectDeltaType objectChange = unmarshalValueFromFile( - REQUEST_USER_MODIFY_ADD_ACCOUNT_DERBY_FILENAME, ObjectDeltaType.class); - - // WHEN ObjectTypes.USER.getTypeQName(), - OperationResultType result = modifyObjectViaModelWS(objectChange); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("modifyObject has failed", result); - - // Check if user object was modified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - - PrismObject uObject = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); - UserType repoUser = uObject.asObjectable(); - - repoResult.computeStatus(); - display("User (repository)", repoUser); - - List accountRefs = repoUser.getLinkRef(); - // OpenDJ account was added in previous test, hence 2 accounts - assertEquals(2, accountRefs.size()); - - ObjectReferenceType accountRef = null; - for (ObjectReferenceType ref : accountRefs) { - if (!ref.getOid().equals(accountShadowOidOpendj)) { - accountRef = ref; - } - } - - accountShadowOidDerby = accountRef.getOid(); - assertFalse(accountShadowOidDerby.isEmpty()); - - // Check if shadow was created in the repo - repoResult = new OperationResult("getObject"); - - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidDerby, - null, repoResult); - ShadowType repoShadowType = repoShadow.asObjectable(); - repoResult.computeStatus(); - TestUtil.assertSuccess("addObject has failed", repoResult); - display("Shadow (repository)", repoShadowType); - assertNotNull(repoShadowType); - assertEquals(RESOURCE_DERBY_OID, repoShadowType.getResourceRef().getOid()); - - // Check the "name" property, it should be set to DN, not entryUUID - assertEquals("Wrong name property", PrismTestUtil.createPolyStringType(USER_JACK_DERBY_LOGIN), - repoShadowType.getName()); - - // check attributes in the shadow: should be only identifiers (ICF UID) - String uid = checkRepoShadow(repoShadow); - - // check if account was created in DB Table - - Statement stmt = derbyController.getExecutedStatementWhereLoginName(uid); - ResultSet rs = stmt.getResultSet(); - - System.out.println("RS: " + rs); - - assertTrue("No records found for login name " + uid, rs.next()); - assertEquals(USER_JACK_DERBY_LOGIN, rs.getString(DerbyController.COLUMN_LOGIN)); - assertEquals("Cpt. Jack Sparrow", rs.getString(DerbyController.COLUMN_FULL_NAME)); - // TODO: check password - //assertEquals("3lizab3th",rs.getString(DerbyController.COLUMN_PASSWORD)); - System.out.println("Password: " + rs.getString(DerbyController.COLUMN_PASSWORD)); - - assertFalse("Too many records found for login name " + uid, rs.next()); - rs.close(); - stmt.close(); - - // Use getObject to test fetch of complete shadow - - assertNoRepoThreadLocalCache(); - - Holder resultHolder = new Holder<>(); - Holder objectHolder = new Holder<>(); - SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); - - // WHEN - modelWeb.getObject(ObjectTypes.SHADOW.getTypeQName(), accountShadowOidDerby, - options, objectHolder, resultHolder); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("getObject result", resultHolder.value, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("getObject has failed", resultHolder.value); - - ShadowType modelShadow = (ShadowType) objectHolder.value; - display("Shadow (model)", modelShadow); - - AssertJUnit.assertNotNull(modelShadow); - AssertJUnit.assertEquals(RESOURCE_DERBY_OID, modelShadow.getResourceRef().getOid()); - - assertAttribute(modelShadow, SchemaConstants.ICFS_UID, USER_JACK_DERBY_LOGIN); - assertAttribute(modelShadow, SchemaConstants.ICFS_NAME, USER_JACK_DERBY_LOGIN); - assertAttribute(resourceDerby, modelShadow, "FULL_NAME", "Cpt. Jack Sparrow"); - - } - - @Test - public void test015AccountOwner() throws FaultMessage, ObjectNotFoundException, SchemaException { - // GIVEN - checkRepoOpenDjResource(); - assertNoRepoThreadLocalCache(); - - Holder resultHolder = new Holder<>(); - Holder userHolder = new Holder<>(); - - // WHEN - - modelWeb.findShadowOwner(accountShadowOidOpendj, userHolder, resultHolder); - - // THEN - - display("listAccountShadowOwner result", resultHolder.value); - TestUtil.assertSuccess("listAccountShadowOwner has failed (result)", resultHolder.value); - UserType user = userHolder.value; - assertNotNull("No owner", user); - assertEquals(USER_JACK_OID, user.getOid()); - - System.out.println("Account " + accountShadowOidOpendj + " has owner " + ObjectTypeUtil.toShortString(user)); - } - - @Test - public void test016ProvisioningSearchAccountsIterative() throws Exception { - // GIVEN - OperationResult result = new OperationResult(TestSanity.class.getName() + ".test016ProvisioningSearchAccountsIterative"); - - RefinedResourceSchema refinedSchema = RefinedResourceSchemaImpl.getRefinedSchema(resourceTypeOpenDjrepo, prismContext); - final RefinedObjectClassDefinition refinedAccountDefinition = refinedSchema.getDefaultRefinedDefinition(ShadowKindType.ACCOUNT); - - QName objectClass = refinedAccountDefinition.getObjectClassDefinition().getTypeName(); - ObjectQuery q = ObjectQueryUtil.createResourceAndObjectClassQuery(resourceTypeOpenDjrepo.getOid(), objectClass, prismContext); - - final Collection objects = new HashSet<>(); - final MatchingRule caseIgnoreMatchingRule = matchingRuleRegistry.getMatchingRule(PrismConstants.STRING_IGNORE_CASE_MATCHING_RULE_NAME, DOMUtil.XSD_STRING); - ResultHandler handler = new ResultHandler() { - - @Override - public boolean handle(PrismObject prismObject, OperationResult parentResult) { - ObjectType objectType = prismObject.asObjectable(); - objects.add(objectType); - - display("Found object", objectType); - - assertTrue(objectType instanceof ShadowType); - ShadowType shadow = (ShadowType) objectType; - assertNotNull(shadow.getOid()); - assertNotNull(shadow.getName()); - assertEquals(RESOURCE_OPENDJ_ACCOUNT_OBJECTCLASS, shadow.getObjectClass()); - assertEquals(RESOURCE_OPENDJ_OID, shadow.getResourceRef().getOid()); - String icfUid = getAttributeValue(shadow, getOpenDjPrimaryIdentifierQName()); - assertNotNull("No ICF UID", icfUid); - String icfName = getNormalizedAttributeValue(shadow, refinedAccountDefinition, getOpenDjSecondaryIdentifierQName()); - assertNotNull("No ICF NAME", icfName); - try { - PrismAsserts.assertEquals("Wrong shadow name", caseIgnoreMatchingRule, shadow.getName().getOrig(), icfName); - } catch (SchemaException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } - assertNotNull("Missing LDAP uid", getAttributeValue(shadow, new QName(ResourceTypeUtil.getResourceNamespace(resourceTypeOpenDjrepo), "uid"))); - assertNotNull("Missing LDAP cn", getAttributeValue(shadow, new QName(ResourceTypeUtil.getResourceNamespace(resourceTypeOpenDjrepo), "cn"))); - assertNotNull("Missing LDAP sn", getAttributeValue(shadow, new QName(ResourceTypeUtil.getResourceNamespace(resourceTypeOpenDjrepo), "sn"))); - assertNotNull("Missing activation", shadow.getActivation()); - assertNotNull("Missing activation status", shadow.getActivation().getAdministrativeStatus()); - return true; - } - }; - - // WHEN - - provisioningService.searchObjectsIterative(ShadowType.class, q, null, handler, null, result); - - // THEN - - displayValue("Count", objects.size()); - } - - /** - * We are going to modify the user. As the user has an account, the user - * changes should be also applied to the account (by schemaHandling). - */ - @Test - public void test020ModifyUser() throws Exception { - // GIVEN - - assertNoRepoThreadLocalCache(); - - ObjectDeltaType objectChange = unmarshalValueFromFile( - REQUEST_USER_MODIFY_FULLNAME_LOCALITY_FILENAME, ObjectDeltaType.class); - - // WHEN ObjectTypes.USER.getTypeQName(), - OperationResultType result = modifyObjectViaModelWS(objectChange); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result:", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("modifyObject has failed", result); - - // Check if user object was modified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - PrismObject repoUser = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); - UserType repoUserType = repoUser.asObjectable(); - display("repository user", repoUser); - - PrismAsserts.assertEqualsPolyString("wrong value for fullName", "Cpt. Jack Sparrow", repoUserType.getFullName()); - PrismAsserts.assertEqualsPolyString("wrong value for locality", "somewhere", repoUserType.getLocality()); - assertEquals("wrong value for employeeNumber", "1", repoUserType.getEmployeeNumber()); - - // Check if appropriate accountRef is still there - - List accountRefs = repoUserType.getLinkRef(); - assertEquals(2, accountRefs.size()); - for (ObjectReferenceType accountRef : accountRefs) { - assertTrue("No OID in " + accountRef + " in " + repoUserType, - accountRef.getOid().equals(accountShadowOidOpendj) || - accountRef.getOid().equals(accountShadowOidDerby)); - - } - - // Check if shadow is still in the repo and that it is untouched - - repoResult = new OperationResult("getObject"); - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject(repo) has failed", repoResult); - display("repository shadow", repoShadow); - AssertJUnit.assertNotNull(repoShadow); - ShadowType repoShadowType = repoShadow.asObjectable(); - AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); - - // check attributes in the shadow: should be only identifiers (ICF UID) - - String uid = checkRepoShadow(repoShadow); - - // Check if LDAP account was updated - assertOpenDJAccountJack(uid, "jack"); - } - - private Entry assertOpenDJAccountJack(String entryUuid, String uid) throws DirectoryException { - Entry entry = openDJController.searchAndAssertByEntryUuid(entryUuid); - return assertOpenDJAccountJack(entry, uid); - } - - private Entry assertOpenDJAccountJack(Entry entry, String uid) throws DirectoryException { - return assertOpenDJAccountJack(entry, uid, "Jack"); - } - - private Entry assertOpenDJAccountJack(Entry entry, String uid, String givenName) throws DirectoryException { - display(entry); - - OpenDJController.assertDn(entry, "uid=" + uid + ",ou=people,dc=example,dc=com"); - OpenDJController.assertAttribute(entry, "uid", uid); - if (givenName == null) { - OpenDJController.assertAttribute(entry, "givenName"); - } else { - OpenDJController.assertAttribute(entry, "givenName", givenName); - } - OpenDJController.assertAttribute(entry, "sn", "Sparrow"); - // These two should be assigned from the User modification by - // schemaHandling - OpenDJController.assertAttribute(entry, "cn", "Cpt. Jack Sparrow"); - OpenDJController.assertAttribute(entry, "displayName", "Cpt. Jack Sparrow"); - // This will get translated from "somewhere" to this (outbound - // expression in schemeHandling) -> this is not more supported...we - // don't support complex run-time properties. the value will be - // evaluated from outbound expression - OpenDJController.assertAttribute(entry, "l", "somewhere"); - OpenDJController.assertAttribute(entry, "postalAddress", "Number 1"); - - return entry; - } - - /** - * We are going to change user's password. As the user has an account, the password change - * should be also applied to the account (by schemaHandling). - */ - @Test - public void test022ChangeUserPassword() throws Exception { - // GIVEN - - ObjectDeltaType objectChange = unmarshalValueFromFile( - REQUEST_USER_MODIFY_PASSWORD_FILENAME, ObjectDeltaType.class); - - System.out.println("In modification: " + objectChange.getItemDelta().get(0).getValue().get(0)); - assertNoRepoThreadLocalCache(); - - // WHEN ObjectTypes.USER.getTypeQName(), - OperationResultType result = modifyObjectViaModelWS(objectChange); - - // THEN - assertUserPasswordChange("butUnd3dM4yT4lkAL0t", result); - } - - /** - * Similar to previous test just the request is constructed a bit differently. - */ - @Test - public void test023ChangeUserPasswordJAXB() throws Exception { - // GIVEN - final String NEW_PASSWORD = "abandonSHIP"; - Document doc = ModelClientUtil.getDocumnent(); - - ObjectDeltaType userDelta = new ObjectDeltaType(); - userDelta.setOid(USER_JACK_OID); - userDelta.setChangeType(ChangeTypeType.MODIFY); - userDelta.setObjectType(UserType.COMPLEX_TYPE); - - ItemDeltaType passwordDelta = new ItemDeltaType(); - passwordDelta.setModificationType(ModificationTypeType.REPLACE); - passwordDelta.setPath(ModelClientUtil.createItemPathType("credentials/password/value", prismContext)); - ProtectedStringType pass = new ProtectedStringType(); - pass.setClearValue(NEW_PASSWORD); - XNode passValue = prismContext.xnodeSerializer().root(new QName("dummy")).serializeRealValue(pass).getSubnode(); - System.out.println("PASSWORD VALUE: " + passValue.debugDump()); - RawType passwordValue = new RawType(passValue, prismContext); - passwordDelta.getValue().add(passwordValue); - userDelta.getItemDelta().add(passwordDelta); - - // WHEN ObjectTypes.USER.getTypeQName(), - OperationResultType result = modifyObjectViaModelWS(userDelta); - - // THEN - assertUserPasswordChange(NEW_PASSWORD, result); - } - - private void assertUserPasswordChange(String expectedUserPassword, OperationResultType result) throws ObjectNotFoundException, SchemaException, DirectoryException, EncryptionException { - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result:", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("modifyObject has failed", result); - - // Check if user object was modified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - PrismObject repoUser = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); - UserType repoUserType = repoUser.asObjectable(); - display("repository user", repoUser); - - // Check if nothing else was modified - PrismAsserts.assertEqualsPolyString("wrong repo fullName", "Cpt. Jack Sparrow", repoUserType.getFullName()); - PrismAsserts.assertEqualsPolyString("wrong repo locality", "somewhere", repoUserType.getLocality()); - - // Check if appropriate accountRef is still there - assertLinks(repoUser, 2); - assertLinked(repoUser, accountShadowOidOpendj); - assertLinked(repoUser, accountShadowOidDerby); - - assertPassword(repoUser, expectedUserPassword); - - // Check if shadow is still in the repo and that it is untouched - repoResult = new OperationResult("getObject"); - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); - display("repository shadow", repoShadow); - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject(repo) has failed", repoResult); - ShadowType repoShadowType = repoShadow.asObjectable(); - AssertJUnit.assertNotNull(repoShadowType); - AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); - - // check attributes in the shadow: should be only identifiers (ICF UID) - String uid = checkRepoShadow(repoShadow); - - // Check if LDAP account was updated - Entry entry = assertOpenDJAccountJack(uid, "jack"); - - String ldapPasswordAfter = OpenDJController.getAttributeValue(entry, "userPassword"); - assertNotNull(ldapPasswordAfter); - - displayValue("LDAP password after change", ldapPasswordAfter); - - assertFalse("No change in password (original)", ldapPasswordAfter.equals(originalJacksLdapPassword)); - if (lastJacksLdapPassword != null) { - assertFalse("No change in password (last)", ldapPasswordAfter.equals(lastJacksLdapPassword)); - } - lastJacksLdapPassword = ldapPasswordAfter; - } - - @Test - public void test027ModifyAccountDj() throws Exception { - testModifyAccountDjRoomNumber(REQUEST_ACCOUNT_MODIFY_ROOM_NUMBER_FILE, "quarterdeck"); - } - - @Test - public void test028ModifyAccountDjExplicitType() throws Exception { - testModifyAccountDjRoomNumber(REQUEST_ACCOUNT_MODIFY_ROOM_NUMBER_EXPLICIT_TYPE_FILE, "upperdeck"); - } - - public void testModifyAccountDjRoomNumber(File reqFile, String expectedVal) throws Exception { - // GIVEN - assertNoRepoThreadLocalCache(); - - ObjectDeltaType objectChange = unmarshalValueFromFile(reqFile, ObjectDeltaType.class); - objectChange.setOid(accountShadowOidOpendj); - - // WHEN - OperationResultType result = modifyObjectViaModelWS(objectChange); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result:", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("modifyObject has failed", result); - - OperationResult repoResult = new OperationResult("getObject"); - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject(repo) has failed", repoResult); - display("repository shadow", repoShadow); - AssertJUnit.assertNotNull(repoShadow); - ShadowType repoShadowType = repoShadow.asObjectable(); - AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); - - // check attributes in the shadow: should be only identifiers (ICF UID) - - String uid = checkRepoShadow(repoShadow); - - // Check if LDAP account was updated - Entry jackLdapEntry = assertOpenDJAccountJack(uid, "jack"); - OpenDJController.assertAttribute(jackLdapEntry, "roomNumber", expectedVal); - } - - @Test - public void test029ModifyAccountDjBadPath() throws Exception { - // GIVEN - assertNoRepoThreadLocalCache(); - - ObjectDeltaType objectChange = unmarshalValueFromFile( - REQUEST_ACCOUNT_MODIFY_BAD_PATH_FILE, ObjectDeltaType.class); - objectChange.setOid(accountShadowOidOpendj); - - OperationResultType result; - try { - // WHEN - result = modifyObjectViaModelWS(objectChange); - - AssertJUnit.fail("Unexpected success"); - } catch (FaultMessage f) { - // this is expected - FaultType faultInfo = f.getFaultInfo(); - result = faultInfo.getOperationResult(); - } - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result:", result, SchemaConstants.C_RESULT); - TestUtil.assertFailure(result); - - OperationResult repoResult = new OperationResult("getObject"); - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject(repo) has failed", repoResult); - display("repository shadow", repoShadow); - AssertJUnit.assertNotNull(repoShadow); - ShadowType repoShadowType = repoShadow.asObjectable(); - AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); - - // check attributes in the shadow: should be only identifiers (ICF UID) - - String uid = checkRepoShadow(repoShadow); - - // Check if LDAP account was updated - Entry jackLdapEntry = assertOpenDJAccountJack(uid, "jack"); - OpenDJController.assertAttribute(jackLdapEntry, "roomNumber", "upperdeck"); - } - - /** - * Try to disable user. As the user has an account, the account should be disabled as well. - */ - @Test - public void test030DisableUser() throws Exception { - // GIVEN - ObjectDeltaType objectChange = unmarshalValueFromFile( - REQUEST_USER_MODIFY_ACTIVATION_DISABLE_FILENAME, ObjectDeltaType.class); - - Entry entry = openDJController.searchByUid("jack"); - assertOpenDJAccountJack(entry, "jack"); - - String pwpAccountDisabled = OpenDJController.getAttributeValue(entry, "ds-pwp-account-disabled"); - displayValue("ds-pwp-account-disabled before change", pwpAccountDisabled); - assertTrue("LDAP account is not enabled (precondition)", openDJController.isAccountEnabled(entry)); - - assertNoRepoThreadLocalCache(); - - // WHEN - when(); - OperationResultType result = modifyObjectViaModelWS(objectChange); - - // THEN - then(); - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result:", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("modifyObject has failed", result); - - // Check if user object was modified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - PrismObject repoUser = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); - display("repository user", repoUser); - UserType repoUserType = repoUser.asObjectable(); - - // Check if nothing else was modified - assertEqualsPolyString("wrong repo fullName", "Cpt. Jack Sparrow", repoUserType.getFullName()); - assertEqualsPolyString("wrong repo locality", "somewhere", repoUserType.getLocality()); - - // Check if appropriate accountRef is still there - List accountRefs = repoUserType.getLinkRef(); - assertEquals(2, accountRefs.size()); - for (ObjectReferenceType accountRef : accountRefs) { - assertTrue("No OID in " + accountRef + " in " + repoUserType, - accountRef.getOid().equals(accountShadowOidOpendj) || - accountRef.getOid().equals(accountShadowOidDerby)); - } - - // Check if shadow is still in the repo and that it is untouched - repoResult = new OperationResult("getObject"); - - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); - display("repo shadow", repoShadow); - ShadowType repoShadowType = repoShadow.asObjectable(); - - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject(repo) has failed", repoResult); - AssertJUnit.assertNotNull(repoShadowType); - AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); - - // check attributes in the shadow: should be only identifiers (ICF UID) - String uid = checkRepoShadow(repoShadow); - - // Check if LDAP account was updated - - entry = openDJController.searchAndAssertByEntryUuid(uid); - assertOpenDJAccountJack(entry, "jack"); - - pwpAccountDisabled = OpenDJController.getAttributeValue(entry, "ds-pwp-account-disabled"); - displayValue("ds-pwp-account-disabled after change", pwpAccountDisabled); - assertFalse("LDAP account was not disabled", openDJController.isAccountEnabled(entry)); - - // Use getObject to test fetch of complete shadow - - Holder resultHolder = new Holder<>(); - Holder objectHolder = new Holder<>(); - SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); - assertNoRepoThreadLocalCache(); - - // WHEN - when(); - modelWeb.getObject(ObjectTypes.SHADOW.getTypeQName(), accountShadowOidOpendj, - options, objectHolder, resultHolder); - - // THEN - then(); - assertNoRepoThreadLocalCache(); - displayJaxb("getObject result", resultHolder.value, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("getObject has failed", resultHolder.value); - - ShadowType modelShadow = (ShadowType) objectHolder.value; - display("Shadow (model)", modelShadow); - - AssertJUnit.assertNotNull(modelShadow); - AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, modelShadow.getResourceRef().getOid()); - - assertAttributeNotNull(modelShadow, getOpenDjPrimaryIdentifierQName()); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "uid", "jack"); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "givenName", "Jack"); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "sn", "Sparrow"); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "cn", "Cpt. Jack Sparrow"); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "displayName", "Cpt. Jack Sparrow"); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "l", "somewhere"); - - assertNotNull("The account activation is null in the shadow", modelShadow.getActivation()); - assertNotNull("The account activation status was not present in shadow", modelShadow.getActivation().getAdministrativeStatus()); - assertEquals("The account was not disabled in the shadow", ActivationStatusType.DISABLED, modelShadow.getActivation().getAdministrativeStatus()); - - } - - /** - * Try to enable user after it has been disabled. As the user has an account, the account should be enabled as well. - */ - @Test - public void test031EnableUser() throws Exception { - // GIVEN - ObjectDeltaType objectChange = unmarshalValueFromFile( - REQUEST_USER_MODIFY_ACTIVATION_ENABLE_FILENAME, ObjectDeltaType.class); - assertNoRepoThreadLocalCache(); - - // WHEN ObjectTypes.USER.getTypeQName(), - OperationResultType result = modifyObjectViaModelWS(objectChange); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result:", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("modifyObject has failed", result); - - // Check if user object was modified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - PrismObject uObject = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); - UserType repoUser = uObject.asObjectable(); - display("repo user", repoUser); - - // Check if nothing else was modified - PrismAsserts.assertEqualsPolyString("wrong repo fullName", "Cpt. Jack Sparrow", repoUser.getFullName()); - PrismAsserts.assertEqualsPolyString("wrong repo locality", "somewhere", repoUser.getLocality()); - - // Check if appropriate accountRef is still there - List accountRefs = repoUser.getLinkRef(); - assertEquals(2, accountRefs.size()); - for (ObjectReferenceType accountRef : accountRefs) { - assertTrue("No OID in " + accountRef + " in " + repoUser, - accountRef.getOid().equals(accountShadowOidOpendj) || - accountRef.getOid().equals(accountShadowOidDerby)); - } - - // Check if shadow is still in the repo and that it is untouched - repoResult = new OperationResult("getObject"); - - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, - null, repoResult); - ShadowType repoShadowType = repoShadow.asObjectable(); - - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject(repo) has failed", repoResult); - display("repo shadow", repoShadowType); - AssertJUnit.assertNotNull(repoShadowType); - AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); - - // check attributes in the shadow: should be only identifiers (ICF UID) - String uid = checkRepoShadow(repoShadow); - - // Use getObject to test fetch of complete shadow - - Holder resultHolder = new Holder<>(); - Holder objectHolder = new Holder<>(); - SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); - assertNoRepoThreadLocalCache(); - - // WHEN - modelWeb.getObject(ObjectTypes.SHADOW.getTypeQName(), accountShadowOidOpendj, - options, objectHolder, resultHolder); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("getObject result", resultHolder.value, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("getObject has failed", resultHolder.value); - - ShadowType modelShadow = (ShadowType) objectHolder.value; - display("Shadow (model)", modelShadow); - - AssertJUnit.assertNotNull(modelShadow); - AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, modelShadow.getResourceRef().getOid()); - - assertAttributeNotNull(modelShadow, getOpenDjPrimaryIdentifierQName()); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "uid", "jack"); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "givenName", "Jack"); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "sn", "Sparrow"); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "cn", "Cpt. Jack Sparrow"); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "displayName", "Cpt. Jack Sparrow"); - assertAttribute(resourceTypeOpenDjrepo, modelShadow, "l", "somewhere"); - - assertNotNull("The account activation is null in the shadow", modelShadow.getActivation()); - assertNotNull("The account activation status was not present in shadow", modelShadow.getActivation().getAdministrativeStatus()); - assertEquals("The account was not enabled in the shadow", ActivationStatusType.ENABLED, modelShadow.getActivation().getAdministrativeStatus()); - - // Check if LDAP account was updated - - Entry entry = openDJController.searchAndAssertByEntryUuid(uid); - assertOpenDJAccountJack(entry, "jack"); - - // The value of ds-pwp-account-disabled should have been removed - String pwpAccountDisabled = OpenDJController.getAttributeValue(entry, "ds-pwp-account-disabled"); - System.out.println("ds-pwp-account-disabled after change: " + pwpAccountDisabled); - assertTrue("LDAP account was not enabled", openDJController.isAccountEnabled(entry)); - } - - /** - * Unlink account by removing the accountRef from the user. - * The account will not be deleted, just the association to user will be broken. - */ - @Test - public void test040UnlinkDerbyAccountFromUser() - throws FaultMessage, ObjectNotFoundException, SchemaException { - // GIVEN - - ObjectDeltaType objectChange = new ObjectDeltaType(); - objectChange.setOid(USER_JACK_OID); - ItemDeltaType modificationDeleteAccountRef = new ItemDeltaType(); - modificationDeleteAccountRef.setModificationType(ModificationTypeType.DELETE); - ObjectReferenceType accountRefToDelete = new ObjectReferenceType(); - accountRefToDelete.setOid(accountShadowOidDerby); - RawType modificationValue = new RawType(prismContext.xnodeSerializer().root(new QName("dummy")).serializeRealValue(accountRefToDelete).getSubnode(), prismContext); - modificationDeleteAccountRef.getValue().add(modificationValue); - modificationDeleteAccountRef.setPath(new ItemPathType(UserType.F_LINK_REF)); - objectChange.getItemDelta().add(modificationDeleteAccountRef); - objectChange.setChangeType(ChangeTypeType.MODIFY); - objectChange.setObjectType(UserType.COMPLEX_TYPE); - displayJaxb("modifyObject input", objectChange, new QName(SchemaConstants.NS_C, "change")); - assertNoRepoThreadLocalCache(); - - // WHEN ObjectTypes.USER.getTypeQName(), - OperationResultType result = modifyObjectViaModelWS(objectChange); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("modifyObject has failed", result); - - // Check if user object was modified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - - PrismObject uObject = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); - UserType repoUser = uObject.asObjectable(); - repoResult.computeStatus(); - display("User (repository)", repoUser); - - List accountRefs = repoUser.getLinkRef(); - // only OpenDJ account should be left now - assertEquals(1, accountRefs.size()); - ObjectReferenceType ref = accountRefs.get(0); - assertEquals("Wrong OID in accountRef in " + repoUser, accountShadowOidOpendj, ref.getOid()); - - } - - /** - * Delete the shadow which will cause deletion of associated account. - * The account was unlinked in the previous test, therefore no operation with user is needed. - */ - @Test - public void test041DeleteDerbyAccount() - throws FaultMessage, SchemaException, SQLException { - // GIVEN - - assertNoRepoThreadLocalCache(); - - // WHEN - OperationResultType result = deleteObjectViaModelWS(ObjectTypes.SHADOW.getTypeQName(), accountShadowOidDerby); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("deleteObject result", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("deleteObject has failed", result); - - // Check if shadow was deleted - OperationResult repoResult = new OperationResult("getObject"); - - try { - repositoryService.getObject(ShadowType.class, accountShadowOidDerby, - null, repoResult); - AssertJUnit.fail("Shadow was not deleted"); - } catch (ObjectNotFoundException ex) { - display("Caught expected exception from getObject(shadow): " + ex); - } - - // check if account was deleted in DB Table - - Statement stmt = derbyController.getExecutedStatementWhereLoginName(USER_JACK_DERBY_LOGIN); - ResultSet rs = stmt.getResultSet(); - - System.out.println("RS: " + rs); - - assertFalse("Account was not deleted in database", rs.next()); - - } - - private OperationResultType deleteObjectViaModelWS(QName typeQName, String oid) throws FaultMessage { - ObjectDeltaListType deltaList = new ObjectDeltaListType(); - ObjectDeltaType objectDelta = new ObjectDeltaType(); - objectDelta.setOid(oid); - objectDelta.setObjectType(typeQName); - objectDelta.setChangeType(ChangeTypeType.DELETE); - deltaList.getDelta().add(objectDelta); - ObjectDeltaOperationListType list = modelWeb.executeChanges(deltaList, null); - return getOdoFromDeltaOperationList(list, objectDelta).getExecutionResult(); - } - - @Test - public void test047RenameUser() throws Exception { - // GIVEN - assertNoRepoThreadLocalCache(); - - ObjectDeltaType objectChange = unmarshalValueFromFile( - REQUEST_USER_MODIFY_NAME_FILENAME, ObjectDeltaType.class); - - // WHEN ObjectTypes.USER.getTypeQName(), - OperationResultType result = modifyObjectViaModelWS(objectChange); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result:", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("modifyObject has failed", result); - - // Check if user object was modified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - PrismObject repoUser = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); - UserType repoUserType = repoUser.asObjectable(); - display("repository user", repoUser); - - PrismAsserts.assertEqualsPolyString("wrong value for User name", "jsparrow", repoUserType.getName()); - PrismAsserts.assertEqualsPolyString("wrong value for User fullName", "Cpt. Jack Sparrow", repoUserType.getFullName()); - PrismAsserts.assertEqualsPolyString("wrong value for User locality", "somewhere", repoUserType.getLocality()); - assertEquals("wrong value for employeeNumber", "1", repoUserType.getEmployeeNumber()); - - // Check if appropriate accountRef is still there - - List accountRefs = repoUserType.getLinkRef(); - assertEquals(1, accountRefs.size()); - ObjectReferenceType accountRef = accountRefs.iterator().next(); - assertEquals("Wrong OID in " + accountRef + " in " + repoUserType, - accountShadowOidOpendj, accountRef.getOid()); - - // Check if shadow is still in the repo and that it is untouched - - repoResult = new OperationResult("getObject"); - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject(repo) has failed", repoResult); - display("repository shadow", repoShadow); - AssertJUnit.assertNotNull(repoShadow); - ShadowType repoShadowType = repoShadow.asObjectable(); - AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); - - // check attributes in the shadow: should be only identifiers (ICF UID) - - String uid = checkRepoShadow(repoShadow); - - // Check if LDAP account was updated - assertOpenDJAccountJack(uid, "jsparrow"); - } - - /** - * We are going to modify the user. As the user has an account, the user - * changes should be also applied to the account (by schemaHandling). - */ - @Test - public void test048ModifyUserRemoveGivenName() throws Exception { - // GIVEN - assertNoRepoThreadLocalCache(); - ObjectDeltaType objectChange = unmarshalValueFromFile( - REQUEST_USER_MODIFY_GIVENNAME_FILENAME, ObjectDeltaType.class); - displayJaxb("objectChange:", objectChange, SchemaConstants.T_OBJECT_DELTA); - - // WHEN ObjectTypes.USER.getTypeQName(), - OperationResultType result = modifyObjectViaModelWS(objectChange); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result:", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("modifyObject has failed", result); - - // Check if user object was modified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - PrismObject repoUser = repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); - UserType repoUserType = repoUser.asObjectable(); - display("repository user", repoUser); - - PrismAsserts.assertEqualsPolyString("wrong value for fullName", "Cpt. Jack Sparrow", repoUserType.getFullName()); - assertNull("Value for givenName still present", repoUserType.getGivenName()); - - // Check if appropriate accountRef is still there - - List accountRefs = repoUserType.getLinkRef(); - assertEquals(1, accountRefs.size()); - ObjectReferenceType accountRef = accountRefs.iterator().next(); - accountRef.getOid().equals(accountShadowOidOpendj); - - // Check if shadow is still in the repo and that it is untouched - - repoResult = new OperationResult("getObject"); - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject(repo) has failed", repoResult); - display("repository shadow", repoShadow); - AssertJUnit.assertNotNull(repoShadow); - ShadowType repoShadowType = repoShadow.asObjectable(); - AssertJUnit.assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); - - // check attributes in the shadow: should be only identifiers (ICF UID) - - String uid = checkRepoShadow(repoShadow); - - // Check if LDAP account was updated - Entry entry = openDJController.searchAndAssertByEntryUuid(uid); - assertOpenDJAccountJack(entry, "jsparrow", null); - } - - /** - * The user should have an account now. Let's try to delete the user. The - * account should be gone as well. - */ - @Test - public void test049DeleteUser() throws SchemaException, FaultMessage, DirectoryException { - // GIVEN - - assertNoRepoThreadLocalCache(); - - // WHEN - OperationResultType result = deleteObjectViaModelWS(ObjectTypes.USER.getTypeQName(), USER_JACK_OID); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("deleteObject result", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("deleteObject has failed", result); - - // User should be gone from the repository - OperationResult repoResult = new OperationResult("getObject"); - try { - repositoryService.getObject(UserType.class, USER_JACK_OID, null, repoResult); - AssertJUnit.fail("User still exists in repo after delete"); - } catch (ObjectNotFoundException e) { - // This is expected - } - - // Account shadow should be gone from the repository - repoResult = new OperationResult("getObject"); - try { - repositoryService.getObject(ShadowType.class, accountShadowOidOpendj, null, repoResult); - AssertJUnit.fail("Shadow still exists in repo after delete"); - } catch (ObjectNotFoundException e) { - // This is expected, but check also the result - AssertJUnit.assertFalse("getObject failed as expected, but the result indicates success", - repoResult.isSuccess()); - } - - // Account should be deleted from LDAP - InternalSearchOperation op = openDJController.getInternalConnection().processSearch( - "dc=example,dc=com", SearchScope.WHOLE_SUBTREE, DereferencePolicy.NEVER_DEREF_ALIASES, 100, - 100, false, "(uid=" + USER_JACK_LDAP_UID + ")", null); - - AssertJUnit.assertEquals(0, op.getEntriesSent()); - - } - - @Test - public void test100AssignRolePirate() throws Exception { - // GIVEN - - // IMPORTANT! Assignment enforcement is FULL now - setAssignmentEnforcement(AssignmentPolicyEnforcementType.FULL); - // This is not redundant. It checks that the previous command set the policy correctly - assertSyncSettingsAssignmentPolicyEnforcement(AssignmentPolicyEnforcementType.FULL); - - PrismObject user = PrismTestUtil.parseObject(USER_GUYBRUSH_FILE); - UserType userType = user.asObjectable(); - - // Encrypt the password - protector.encrypt(userType.getCredentials().getPassword().getValue()); - - OperationResultType result = new OperationResultType(); - Holder resultHolder = new Holder<>(result); - Holder oidHolder = new Holder<>(); - assertNoRepoThreadLocalCache(); - - addObjectViaModelWS(userType, null, oidHolder, resultHolder); - - assertNoRepoThreadLocalCache(); - TestUtil.assertSuccess("addObject has failed", resultHolder.value); - - ObjectDeltaType objectChange = unmarshalValueFromFile( - REQUEST_USER_MODIFY_ADD_ROLE_PIRATE_FILENAME, ObjectDeltaType.class); - - // WHEN ObjectTypes.USER.getTypeQName(), - result = modifyObjectViaModelWS(objectChange); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("modifyObject has failed", result); - - // Check if user object was modified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - - PrismObject uObject = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); - UserType repoUser = uObject.asObjectable(); - repoResult.computeStatus(); - display("User (repository)", repoUser); - - List accountRefs = repoUser.getLinkRef(); - assertEquals(1, accountRefs.size()); - ObjectReferenceType accountRef = accountRefs.get(0); - accountShadowOidGuybrushOpendj = accountRef.getOid(); - assertFalse(accountShadowOidGuybrushOpendj.isEmpty()); - - // Check if shadow was created in the repo - - repoResult = new OperationResult("getObject"); - - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, - null, repoResult); - ShadowType repoShadowType = repoShadow.asObjectable(); - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject has failed", repoResult); - display("Shadow (repository)", repoShadowType); - assertNotNull(repoShadowType); - assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); - - accountGuybrushOpendjEntryUuuid = checkRepoShadow(repoShadow); - - // check if account was created in LDAP - - Entry entry = openDJController.searchAndAssertByEntryUuid(accountGuybrushOpendjEntryUuuid); - - display("LDAP account", entry); - - OpenDJController.assertAttribute(entry, "uid", "guybrush"); - OpenDJController.assertAttribute(entry, "givenName", "Guybrush"); - OpenDJController.assertAttribute(entry, "sn", "Threepwood"); - OpenDJController.assertAttribute(entry, "cn", "Guybrush Threepwood"); - OpenDJController.assertAttribute(entry, "displayName", "Guybrush Threepwood"); - // The "l" attribute is assigned indirectly through schemaHandling and - // config object - OpenDJController.assertAttribute(entry, "l", "Deep in the Caribbean"); - - // Set by the role - OpenDJController.assertAttribute(entry, "employeeType", "sailor"); - OpenDJController.assertAttribute(entry, "title", "Bloody Pirate"); - OpenDJController.assertAttribute(entry, "businessCategory", "loot", "murder"); - - String guybrushPassword = OpenDJController.getAttributeValue(entry, "userPassword"); - assertNotNull("Pasword was not set on create", guybrushPassword); - - // TODO: Derby - - } - - @Test - public void test101AccountOwnerAfterRole() throws Exception { - // GIVEN - - assertNoRepoThreadLocalCache(); - - Holder resultHolder = new Holder<>(); - Holder userHolder = new Holder<>(); - - // WHEN - - modelWeb.findShadowOwner(accountShadowOidGuybrushOpendj, userHolder, resultHolder); - - // THEN - - TestUtil.assertSuccess("listAccountShadowOwner has failed (result)", resultHolder.value); - UserType user = userHolder.value; - assertNotNull("No owner", user); - assertEquals(USER_GUYBRUSH_OID, user.getOid()); - - System.out.println("Account " + accountShadowOidGuybrushOpendj + " has owner " + ObjectTypeUtil.toShortString(user)); - } - - @Test - public void test102AssignRoleCaptain() throws Exception { - // GIVEN - - ObjectDeltaType objectChange = unmarshalValueFromFile( - REQUEST_USER_MODIFY_ADD_ROLE_CAPTAIN_1_FILENAME, ObjectDeltaType.class); - - // WHEN ObjectTypes.USER.getTypeQName(), - OperationResultType result = modifyObjectViaModelWS(objectChange); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("modifyObject has failed", result); - - // Check if user object was modified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - - PrismObject uObject = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); - UserType repoUser = uObject.asObjectable(); - repoResult.computeStatus(); - display("User (repository)", repoUser); - - List accountRefs = repoUser.getLinkRef(); - assertEquals(1, accountRefs.size()); - ObjectReferenceType accountRef = accountRefs.get(0); - assertEquals(accountShadowOidGuybrushOpendj, accountRef.getOid()); - - // Check if shadow is still in the repo - - repoResult = new OperationResult("getObject"); - - PrismObject aObject = repositoryService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, - null, repoResult); - ShadowType repoShadow = aObject.asObjectable(); - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject has failed", repoResult); - display("Shadow (repository)", repoShadow); - assertNotNull(repoShadow); - assertEquals(RESOURCE_OPENDJ_OID, repoShadow.getResourceRef().getOid()); - - // check if account is still in LDAP - - Entry entry = openDJController.searchAndAssertByEntryUuid(accountGuybrushOpendjEntryUuuid); - - display("LDAP account", entry); - - OpenDJController.assertAttribute(entry, "uid", "guybrush"); - OpenDJController.assertAttribute(entry, "givenName", "Guybrush"); - OpenDJController.assertAttribute(entry, "sn", "Threepwood"); - OpenDJController.assertAttribute(entry, "cn", "Guybrush Threepwood"); - OpenDJController.assertAttribute(entry, "displayName", "Guybrush Threepwood"); - // The "l" attribute is assigned indirectly through schemaHandling and - // config object - OpenDJController.assertAttribute(entry, "l", "Deep in the Caribbean"); - - // Set by the role - OpenDJController.assertAttribute(entry, "employeeType", "sailor"); - OpenDJController.assertAttribute(entry, "title", "Bloody Pirate", "Honorable Captain"); - OpenDJController.assertAttribute(entry, "carLicense", "C4PT41N"); - OpenDJController.assertAttribute(entry, "businessCategory", "loot", "murder", "cruise"); - // Expression in the role taking that from the user - OpenDJController.assertAttribute(entry, "destinationIndicator", "Guybrush Threepwood"); - OpenDJController.assertAttribute(entry, "departmentNumber", "Department of Guybrush"); - // Expression in the role taking that from the assignment - OpenDJController.assertAttribute(entry, "physicalDeliveryOfficeName", "The Sea Monkey"); - - String guybrushPassword = OpenDJController.getAttributeValue(entry, "userPassword"); - assertNotNull("Pasword disappeared", guybrushPassword); - - // TODO: Derby - - } - - /** - * Assign the same "captain" role again, this time with a slightly different assignment parameters. - */ - @Test - public void test103AssignRoleCaptainAgain() throws Exception { - // GIVEN - - ObjectDeltaType objectChange = unmarshalValueFromFile( - REQUEST_USER_MODIFY_ADD_ROLE_CAPTAIN_2_FILENAME, ObjectDeltaType.class); - - // WHEN ObjectTypes.USER.getTypeQName(), - OperationResultType result = modifyObjectViaModelWS(objectChange); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("modifyObject has failed", result); - - // Check if user object was modified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - - PrismObject uObject = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); - UserType repoUser = uObject.asObjectable(); - repoResult.computeStatus(); - display("User (repository)", repoUser); - - List accountRefs = repoUser.getLinkRef(); - assertEquals(1, accountRefs.size()); - ObjectReferenceType accountRef = accountRefs.get(0); - assertEquals(accountShadowOidGuybrushOpendj, accountRef.getOid()); - - // Check if shadow is still in the repo - - repoResult = new OperationResult("getObject"); - - PrismObject aObject = repositoryService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, - null, repoResult); - ShadowType repoShadow = aObject.asObjectable(); - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject has failed", repoResult); - display("Shadow (repository)", repoShadow); - assertNotNull(repoShadow); - assertEquals(RESOURCE_OPENDJ_OID, repoShadow.getResourceRef().getOid()); - - // check if account is still in LDAP - - Entry entry = openDJController.searchAndAssertByEntryUuid(accountGuybrushOpendjEntryUuuid); - - display("LDAP account", entry); - - OpenDJController.assertAttribute(entry, "uid", "guybrush"); - OpenDJController.assertAttribute(entry, "givenName", "Guybrush"); - OpenDJController.assertAttribute(entry, "sn", "Threepwood"); - OpenDJController.assertAttribute(entry, "cn", "Guybrush Threepwood"); - OpenDJController.assertAttribute(entry, "displayName", "Guybrush Threepwood"); - // The "l" attribute is assigned indirectly through schemaHandling and - // config object - OpenDJController.assertAttribute(entry, "l", "Deep in the Caribbean"); - - // Set by the role - OpenDJController.assertAttribute(entry, "employeeType", "sailor"); - OpenDJController.assertAttribute(entry, "title", "Bloody Pirate", "Honorable Captain"); - OpenDJController.assertAttribute(entry, "carLicense", "C4PT41N"); - OpenDJController.assertAttribute(entry, "businessCategory", "loot", "murder", "cruise"); - // Expression in the role taking that from the user - OpenDJController.assertAttribute(entry, "destinationIndicator", "Guybrush Threepwood"); - OpenDJController.assertAttribute(entry, "departmentNumber", "Department of Guybrush"); - // Expression in the role taking that from the assignments (both of them) - OpenDJController.assertAttribute(entry, "physicalDeliveryOfficeName", "The Sea Monkey", "The Dainty Lady"); - - String guybrushPassword = OpenDJController.getAttributeValue(entry, "userPassword"); - assertNotNull("Pasword disappeared", guybrushPassword); - - // TODO: Derby - - } - - @Test - public void test105ModifyAccount() throws Exception { - // GIVEN - ObjectDeltaType objectChange = unmarshalValueFromFile( - REQUEST_ACCOUNT_MODIFY_ATTRS_FILE, ObjectDeltaType.class); - objectChange.setOid(accountShadowOidGuybrushOpendj); - - // WHEN ObjectTypes.SHADOW.getTypeQName(), - OperationResultType result = modifyObjectViaModelWS(objectChange); - - Task task = taskManager.createTaskInstance(); - OperationResult parentResult = createOperationResult("get after first modify"); - PrismObject shadow = modelService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, null, task, parentResult); - assertNotNull("shadow must not be null", shadow); - - ShadowType shadowType = shadow.asObjectable(); - QName employeeTypeQName = new QName(resourceTypeOpenDjrepo.getNamespace(), "employeeType"); - ItemPath employeeTypePath = ItemPath.create(ShadowType.F_ATTRIBUTES, employeeTypeQName); - PrismProperty item = shadow.findProperty(employeeTypePath); - - PropertyDelta deleteDelta = prismContext.deltaFactory().property().create(ShadowType.F_ATTRIBUTES, item.getDefinition().getItemName(), item.getDefinition()); -// PropertyDelta deleteDelta = PropertyDelta.createDelta(employeeTypePath, shadow.getDefinition()); -// PrismPropertyValue valToDelte = new PrismPropertyValue("A"); -// valToDelte.setParent(deleteDelta); - Collection> values = item.getValues(); - for (PrismPropertyValue val : values) { - if ("A".equals(val.getValue())) { - deleteDelta.addValueToDelete(val.clone()); - } - } - - ObjectDelta delta = prismContext.deltaFactory().object().create(ShadowType.class, ChangeType.MODIFY); - delta.addModification(deleteDelta); - delta.setOid(accountShadowOidGuybrushOpendj); - Collection> deltas = new ArrayList<>(); - deltas.add(delta); - logger.info("-------->>EXECUTE DELETE MODIFICATION<<------------"); - modelService.executeChanges(deltas, null, task, parentResult); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("modifyObject has failed", result); - - // check if LDAP account was modified - - Entry entry = openDJController.searchAndAssertByEntryUuid(accountGuybrushOpendjEntryUuuid); - - display("LDAP account", entry); - - OpenDJController.assertAttribute(entry, "uid", "guybrush"); - OpenDJController.assertAttribute(entry, "givenName", "Guybrush"); - OpenDJController.assertAttribute(entry, "sn", "Threepwood"); - OpenDJController.assertAttribute(entry, "cn", "Guybrush Threepwood"); - OpenDJController.assertAttribute(entry, "displayName", "Guybrush Threepwood"); - // The "l" attribute is assigned indirectly through schemaHandling and - // config object - OpenDJController.assertAttribute(entry, "l", "Deep in the Caribbean"); - - OpenDJController.assertAttribute(entry, "roomNumber", "captain's cabin"); - - // Set by the role - OpenDJController.assertAttribute(entry, "employeeType", "sailor"); - OpenDJController.assertAttribute(entry, "title", "Bloody Pirate", "Honorable Captain"); - OpenDJController.assertAttribute(entry, "carLicense", "C4PT41N"); - OpenDJController.assertAttribute(entry, "businessCategory", "loot", "murder", "cruise", "fighting", "capsize"); - // Expression in the role taking that from the user - OpenDJController.assertAttribute(entry, "destinationIndicator", "Guybrush Threepwood"); - OpenDJController.assertAttribute(entry, "departmentNumber", "Department of Guybrush"); - // Expression in the role taking that from the assignments (both of them) - OpenDJController.assertAttribute(entry, "physicalDeliveryOfficeName", "The Sea Monkey", "The Dainty Lady"); - - String guybrushPassword = OpenDJController.getAttributeValue(entry, "userPassword"); - assertNotNull("Pasword disappeared", guybrushPassword); - - } - - /** - * Judge role excludes pirate role. This assignment should fail. - */ - @Test - public void test104AssignRoleJudge() throws Exception { - // GIVEN - OperationResultType result = new OperationResultType(); - Holder resultHolder = new Holder<>(result); - Holder oidHolder = new Holder<>(); - assertNoRepoThreadLocalCache(); - - ObjectDeltaType objectChange = unmarshalValueFromFile( - REQUEST_USER_MODIFY_ADD_ROLE_JUDGE_FILENAME, ObjectDeltaType.class); - try { - - // WHEN ObjectTypes.USER.getTypeQName(), - result = modifyObjectViaModelWS(objectChange); - - // THEN - AssertJUnit.fail("Expected a failure after assigning conflicting roles but nothing happened and life goes on"); - } catch (FaultMessage f) { - // This is expected - // TODO: check if the fault is the right one - } - - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("modifyObject has failed", result); - - // Check if user object remain unmodified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - - PrismObject uObject = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); - UserType repoUser = uObject.asObjectable(); - repoResult.computeStatus(); - display("User (repository)", repoUser); - - List accountRefs = repoUser.getLinkRef(); - assertEquals("Unexpected number or accountRefs", 1, accountRefs.size()); - - } - - @Test - public void test107UnassignRolePirate() throws Exception { - // GIVEN - assertNoRepoThreadLocalCache(); - - ObjectDeltaType objectChange = unmarshalValueFromFile( - REQUEST_USER_MODIFY_DELETE_ROLE_PIRATE_FILENAME, ObjectDeltaType.class); - - // WHEN ObjectTypes.USER.getTypeQName(), - OperationResultType result = modifyObjectViaModelWS(objectChange); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("modifyObject has failed", result); - - // Check if user object was modified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - - PrismObject repoUser = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); - UserType repoUserType = repoUser.asObjectable(); - repoResult.computeStatus(); - display("User (repository)", repoUser); - - List accountRefs = repoUserType.getLinkRef(); - assertEquals(1, accountRefs.size()); - ObjectReferenceType accountRef = accountRefs.get(0); - assertEquals(accountShadowOidGuybrushOpendj, accountRef.getOid()); - - // Check if shadow is still in the repo - - repoResult = new OperationResult("getObject"); - - PrismObject aObject = repositoryService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, - null, repoResult); - ShadowType repoShadow = aObject.asObjectable(); - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject has failed", repoResult); - display("Shadow (repository)", repoShadow); - assertNotNull(repoShadow); - assertEquals(RESOURCE_OPENDJ_OID, repoShadow.getResourceRef().getOid()); - - // check if account is still in LDAP - - Entry entry = openDJController.searchAndAssertByEntryUuid(accountGuybrushOpendjEntryUuuid); - - display("LDAP account", entry); - - OpenDJController.assertAttribute(entry, "uid", "guybrush"); - OpenDJController.assertAttribute(entry, "givenName", "Guybrush"); - OpenDJController.assertAttribute(entry, "sn", "Threepwood"); - OpenDJController.assertAttribute(entry, "cn", "Guybrush Threepwood"); - OpenDJController.assertAttribute(entry, "displayName", "Guybrush Threepwood"); - // The "l" attribute is assigned indirectly through schemaHandling and - // config object - OpenDJController.assertAttribute(entry, "l", "Deep in the Caribbean"); - - // Set by the role - OpenDJController.assertAttribute(entry, "employeeType", "sailor"); - OpenDJController.assertAttribute(entry, "title", "Honorable Captain"); - OpenDJController.assertAttribute(entry, "carLicense", "C4PT41N"); - OpenDJController.assertAttribute(entry, "businessCategory", "cruise", "fighting", "capsize"); - // Expression in the role taking that from the user - OpenDJController.assertAttribute(entry, "destinationIndicator", "Guybrush Threepwood"); - OpenDJController.assertAttribute(entry, "departmentNumber", "Department of Guybrush"); - // Expression in the role taking that from the assignments (both of them) - OpenDJController.assertAttribute(entry, "physicalDeliveryOfficeName", "The Sea Monkey", "The Dainty Lady"); - - String guybrushPassword = OpenDJController.getAttributeValue(entry, "userPassword"); - assertNotNull("Pasword disappeared", guybrushPassword); - - // TODO: Derby - - } - - @Test - public void test108UnassignRoleCaptain() throws Exception { - // GIVEN - assertNoRepoThreadLocalCache(); - - ObjectDeltaType objectChange = unmarshalValueFromFile( - REQUEST_USER_MODIFY_DELETE_ROLE_CAPTAIN_1_FILENAME, ObjectDeltaType.class); - - // WHEN ObjectTypes.USER.getTypeQName(), - OperationResultType result = modifyObjectViaModelWS(objectChange); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("modifyObject has failed", result); - - // Check if user object was modified in the repo - - // Check if user object was modified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - - PrismObject repoUser = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); - UserType repoUserType = repoUser.asObjectable(); - repoResult.computeStatus(); - display("User (repository)", repoUser); - - List accountRefs = repoUserType.getLinkRef(); - assertEquals(1, accountRefs.size()); - ObjectReferenceType accountRef = accountRefs.get(0); - assertEquals(accountShadowOidGuybrushOpendj, accountRef.getOid()); - - // Check if shadow is still in the repo - - repoResult = new OperationResult("getObject"); - - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, - null, repoResult); - ShadowType repoShadowType = repoShadow.asObjectable(); - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject has failed", repoResult); - display("Shadow (repository)", repoShadow); - assertNotNull(repoShadowType); - assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); - - // check if account is still in LDAP - - Entry entry = openDJController.searchAndAssertByEntryUuid(accountGuybrushOpendjEntryUuuid); - - display("LDAP account", entry); - - OpenDJController.assertAttribute(entry, "uid", "guybrush"); - OpenDJController.assertAttribute(entry, "givenName", "Guybrush"); - OpenDJController.assertAttribute(entry, "sn", "Threepwood"); - OpenDJController.assertAttribute(entry, "cn", "Guybrush Threepwood"); - OpenDJController.assertAttribute(entry, "displayName", "Guybrush Threepwood"); - // The "l" attribute is assigned indirectly through schemaHandling and - // config object - OpenDJController.assertAttribute(entry, "l", "Deep in the Caribbean"); - - // Set by the role - OpenDJController.assertAttribute(entry, "employeeType", "sailor"); - OpenDJController.assertAttribute(entry, "title", "Honorable Captain"); - OpenDJController.assertAttribute(entry, "carLicense", "C4PT41N"); - OpenDJController.assertAttribute(entry, "businessCategory", "cruise", "fighting", "capsize"); - // Expression in the role taking that from the user - OpenDJController.assertAttribute(entry, "destinationIndicator", "Guybrush Threepwood"); - OpenDJController.assertAttribute(entry, "departmentNumber", "Department of Guybrush"); - // Expression in the role taking that from the assignments (both of them) - OpenDJController.assertAttribute(entry, "physicalDeliveryOfficeName", "The Dainty Lady"); - - String guybrushPassword = OpenDJController.getAttributeValue(entry, "userPassword"); - assertNotNull("Pasword disappeared", guybrushPassword); - - // TODO: Derby - - } - - /** - * Captain role was assigned twice. It has to also be unassigned twice. - */ - @Test - public void test109UnassignRoleCaptainAgain() throws Exception { - // GIVEN - - assertNoRepoThreadLocalCache(); - - ObjectDeltaType objectChange = unmarshalValueFromFile( - REQUEST_USER_MODIFY_DELETE_ROLE_CAPTAIN_2_FILENAME, ObjectDeltaType.class); - - // WHEN ObjectTypes.USER.getTypeQName(), - OperationResultType result = modifyObjectViaModelWS(objectChange); - - // THEN - assertNoRepoThreadLocalCache(); - displayJaxb("modifyObject result", result, SchemaConstants.C_RESULT); - - //TODO TODO TODO TODO operation result from repostiory.getObject is unknown...find out why.. -// assertSuccess("modifyObject has failed", result); - - // Check if user object was modified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - - PrismObject repoUser = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); - UserType repoUserType = repoUser.asObjectable(); - repoResult.computeStatus(); - display("User (repository)", repoUserType); - - List accountRefs = repoUserType.getLinkRef(); - assertEquals(0, accountRefs.size()); - - // Check if shadow was deleted from the repo - - repoResult = new OperationResult("getObject"); - - try { - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, - null, repoResult); - AssertJUnit.fail("Account shadow was not deleted from repo"); - } catch (ObjectNotFoundException ex) { - // This is expected - } - - // check if account was deleted from LDAP - - Entry entry = openDJController.searchByEntryUuid(accountGuybrushOpendjEntryUuuid); - - display("LDAP account", entry); - - assertNull("LDAP account was not deleted", entry); - - // TODO: Derby - - } - - // Synchronization tests - - /** - * Test initialization of synchronization. It will create a cycle task and - * check if the cycle executes No changes are synchronized yet. - */ - @Test - public void test300LiveSyncInit() throws Exception { - // Now it is the right time to add task definition to the repository - // We don't want it there any sooner, as it may interfere with the - // previous tests - - checkAllShadows(); - - // IMPORTANT! Assignment enforcement is POSITIVE now - setAssignmentEnforcement(AssignmentPolicyEnforcementType.POSITIVE); - // This is not redundant. It checks that the previous command set the policy correctly - assertSyncSettingsAssignmentPolicyEnforcement(AssignmentPolicyEnforcementType.POSITIVE); - - final OperationResult result = createOperationResult(); - - repoAddObjectFromFile(TASK_OPENDJ_SYNC_FILENAME, result); - - // We need to wait for a sync interval, so the task scanner has a chance - // to pick up this - // task - - waitFor("Waiting for task manager to pick up the task", new Checker() { - public boolean check() throws ObjectNotFoundException, SchemaException { - Task task = taskManager.getTaskPlain(TASK_OPENDJ_SYNC_OID, result); - display("Task while waiting for task manager to pick up the task", task); - // wait until the task is picked up - return task.getLastRunFinishTimestamp() != null; - } - - @Override - public void timeout() { - // No reaction, the test will fail right after return from this - } - }, 20000); - - // Check task status - - Task task = taskManager.getTaskWithResult(TASK_OPENDJ_SYNC_OID, result); - result.computeStatus(); - display("getTask result", result); - TestUtil.assertSuccess("getTask has failed", result); - AssertJUnit.assertNotNull(task); - display("Task after pickup", task); - - PrismObject o = repositoryService.getObject(TaskType.class, TASK_OPENDJ_SYNC_OID, null, result); - display("Task after pickup in the repository", o.asObjectable()); - - // .. it should be running - AssertJUnit.assertEquals(TaskExecutionStatus.RUNNABLE, task.getExecutionStatus()); - - // .. and claimed -// AssertJUnit.assertEquals(TaskExclusivityStatus.CLAIMED, task.getExclusivityStatus()); - - // .. and last run should not be zero - assertNotNull("No lastRunStartTimestamp", task.getLastRunStartTimestamp()); - assertFalse("Zero lastRunStartTimestamp", task.getLastRunStartTimestamp().longValue() == 0); - assertNotNull("No lastRunFinishedTimestamp", task.getLastRunFinishTimestamp()); - assertFalse("Zero lastRunFinishedTimestamp", task.getLastRunFinishTimestamp().longValue() == 0); - - // Test for extension. This will also roughly test extension processor - // and schema processor - PrismContainer taskExtension = task.getExtensionOrClone(); - AssertJUnit.assertNotNull(taskExtension); - display("Task extension", taskExtension); - PrismProperty shipStateProp = taskExtension.findProperty(MY_SHIP_STATE); - AssertJUnit.assertEquals("Wrong 'shipState' property value", "capsized", shipStateProp.getValue().getValue()); - PrismProperty deadProp = taskExtension.findProperty(MY_DEAD); - PrismPropertyValue deadPVal = deadProp.getValues().iterator().next(); - AssertJUnit.assertEquals("Wrong 'dead' property class", Integer.class, deadPVal.getValue().getClass()); - AssertJUnit.assertEquals("Wrong 'dead' property value", Integer.valueOf(42), deadPVal.getValue()); - - // The progress should be 0, as there were no changes yet - AssertJUnit.assertEquals(0, task.getProgress()); - - // Test for presence of a result. It should be there and it should - // indicate success - OperationResult taskResult = task.getResult(); - AssertJUnit.assertNotNull(taskResult); - - assertTrue("Task result is not a success, it is " + taskResult, taskResult.isSuccess()); - - final Object tokenAfter = findSyncToken(task); - displayValue("Sync token after", tokenAfter.toString()); - lastSyncToken = (Integer) tokenAfter; - - checkAllShadows(); - - // Try without options. The results should NOT be there - // MID-4670 - task = taskManager.getTaskPlain(TASK_OPENDJ_SYNC_OID, null, result); - taskResult = task.getResult(); - AssertJUnit.assertNull("Unexpected task result", taskResult); - - } - - /** - * Create LDAP object. That should be picked up by liveSync and a user - * should be created in repo. - */ - @Test - public void test301LiveSyncCreate() throws Exception { - // Sync task should be running (tested in previous test), so just create - // new LDAP object. - - final OperationResult result = createOperationResult(); - final Task syncCycle = taskManager.getTaskPlain(TASK_OPENDJ_SYNC_OID, result); - AssertJUnit.assertNotNull(syncCycle); - - final Object tokenBefore = findSyncToken(syncCycle); - displayValue("Sync token before", tokenBefore.toString()); - - // WHEN - when(); - - Entry entry = openDJController.addEntryFromLdifFile(LDIF_WILL_FILENAME); - display("Entry from LDIF", entry); - - // Wait a bit to give the sync cycle time to detect the change - basicWaitForSyncChangeDetection(syncCycle, tokenBefore, 2, result); - - // THEN - then(); - // Search for the user that should be created now - UserType user = searchUserByName(WILL_NAME); - - PrismAsserts.assertEqualsPolyString("Wrong name.", WILL_NAME, user.getName()); - assertNotNull(user.getLinkRef()); - assertFalse(user.getLinkRef().isEmpty()); -// AssertJUnit.assertEquals(user.getName(), WILL_NAME); - - // TODO: more checks - - assertAndStoreSyncTokenIncrement(syncCycle, 2); - checkAllShadows(); - } - - @Test - public void test302LiveSyncModify() throws Exception { - final OperationResult result = createOperationResult(); - final Task syncCycle = taskManager.getTaskPlain(TASK_OPENDJ_SYNC_OID, result); - AssertJUnit.assertNotNull(syncCycle); - - int tokenBefore = findSyncToken(syncCycle); - displayValue("Sync token before", tokenBefore); - - // WHEN - display("Modifying LDAP entry"); - ChangeRecordEntry entry = openDJController.executeLdifChange(LDIF_WILL_MODIFY_FILE); - - // THEN - displayValue("Entry from LDIF", entry); - - // Wait a bit to give the sync cycle time to detect the change - basicWaitForSyncChangeDetection(syncCycle, tokenBefore, 1, result); - // Search for the user that should be created now - UserType user = searchUserByName(WILL_NAME); - -// AssertJUnit.assertEquals(WILL_NAME, user.getName()); - PrismAsserts.assertEqualsPolyString("Wrong name.", WILL_NAME, user.getName()); - PrismAsserts.assertEqualsPolyString("wrong givenName", "asdf", user.getGivenName()); - - assertAndStoreSyncTokenIncrement(syncCycle, 1); - checkAllShadows(); - } - - @Test - public void test303LiveSyncLink() throws Exception { - // GIVEN - assertNoRepoThreadLocalCache(); - PrismObject user = PrismTestUtil.parseObject(USER_E_LINK_ACTION_FILE); - UserType userType = user.asObjectable(); - final String userOid = userType.getOid(); - // Encrypt e's password - protector.encrypt(userType.getCredentials().getPassword().getValue()); - // create user in repository - OperationResultType resultType = new OperationResultType(); - Holder resultHolder = new Holder<>(resultType); - Holder oidHolder = new Holder<>(); - display("Adding user object", userType); - addObjectViaModelWS(userType, null, oidHolder, resultHolder); - //check results - assertNoRepoThreadLocalCache(); - displayJaxb("addObject result:", resultHolder.value, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("addObject has failed", resultHolder.value); -// AssertJUnit.assertEquals(userOid, oidHolder.value); - - //WHEN - when(); - - //create account for e which should be correlated - final OperationResult result = createOperationResult(); - final Task syncCycle = taskManager.getTaskPlain(TASK_OPENDJ_SYNC_OID, result); - AssertJUnit.assertNotNull(syncCycle); - - int tokenBefore = findSyncToken(syncCycle); - displayValue("Sync token before", tokenBefore); - - Entry entry = openDJController.addEntryFromLdifFile(LDIF_E_FILENAME_LINK); - display("Entry from LDIF", entry); - - // Wait a bit to give the sync cycle time to detect the change - basicWaitForSyncChangeDetection(syncCycle, tokenBefore, 1, result); - - // THEN - then(); - - //check user and account ref - userType = searchUserByName("e"); - - List accountRefs = userType.getLinkRef(); - assertEquals("Account ref not found, or found too many", 1, accountRefs.size()); - - //check account defined by account ref - String accountOid = accountRefs.get(0).getOid(); - ShadowType account = searchAccountByOid(accountOid); - - assertEqualsPolyString("Name doesn't match", "uid=e,ou=People,dc=example,dc=com", account.getName()); - - assertAndStoreSyncTokenIncrement(syncCycle, 1); - checkAllShadows(); - } - - /** - * Create LDAP object. That should be picked up by liveSync and a user - * should be created in repo. - * Also location (ldap l) should be updated through outbound - */ - @Test - public void test304LiveSyncCreateNoLocation() throws Exception { - // Sync task should be running (tested in previous test), so just create - // new LDAP object. - - final OperationResult result = createOperationResult(); - final Task syncCycle = taskManager.getTaskPlain(TASK_OPENDJ_SYNC_OID, result); - AssertJUnit.assertNotNull(syncCycle); - - int tokenBefore = findSyncToken(syncCycle); - displayValue("Sync token before", tokenBefore); - - // WHEN - Entry entry = openDJController.addEntryFromLdifFile(LDIF_WILL_WITHOUT_LOCATION_FILENAME); - display("Entry from LDIF", entry); - - // THEN - // Wait a bit to give the sync cycle time to detect the change - basicWaitForSyncChangeDetection(syncCycle, tokenBefore, 3, result, 60000); - // Search for the user that should be created now - final String userName = "wturner1"; - UserType user = searchUserByName(userName); - - List accountRefs = user.getLinkRef(); - assertEquals("Account ref not found, or found too many", 1, accountRefs.size()); - - //check account defined by account ref - String accountOid = accountRefs.get(0).getOid(); - ShadowType account = searchAccountByOid(accountOid); - - assertEqualsPolyString("Name doesn't match", "uid=" + userName + ",ou=People,dc=example,dc=com", account.getName()); -// assertEquals("Name doesn't match", "uid=" + userName + ",ou=People,dc=example,dc=com", account.getName()); - Collection localities = getAttributeValues(account, new QName(RESOURCE_OPENDJ_ACCOUNT_OBJECTCLASS.getNamespaceURI(), "l")); - assertNotNull("null value list for attribute 'l'", localities); - assertEquals("unexpected number of values of attribute 'l'", 1, localities.size()); - assertEquals("Locality doesn't match", "middle of nowhere", localities.iterator().next()); - - assertAndStoreSyncTokenIncrement(syncCycle, 3); - checkAllShadows(); - } - - private void assertAndStoreSyncTokenIncrement(Task syncCycle, int increment) { - final Object tokenAfter = findSyncToken(syncCycle); - displayValue("Sync token after", tokenAfter.toString()); - int tokenAfterInt = (Integer) tokenAfter; - int expectedToken = lastSyncToken + increment; - lastSyncToken = tokenAfterInt; - assertEquals("Unexpected sync toke value", expectedToken, tokenAfterInt); - } - - private int findSyncToken(Task syncCycle) { - return (Integer) findSyncTokenObject(syncCycle); - } - - private Object findSyncTokenObject(Task syncCycle) { - Object token = null; - PrismProperty tokenProperty = syncCycle.getExtensionOrClone().findProperty(SchemaConstants.SYNC_TOKEN); - if (tokenProperty != null) { - Collection values = tokenProperty.getRealValues(); - if (values.size() > 1) { - throw new IllegalStateException("Too must values in token " + tokenProperty); - } - token = values.iterator().next(); - } - - return token; - } - - /** - * Not really a test. Just cleans up after live sync. - */ - @Test - public void test399LiveSyncCleanup() throws Exception { - final OperationResult result = createOperationResult(); - - taskManager.deleteTask(TASK_OPENDJ_SYNC_OID, result); - - // TODO: check if the task is really stopped - } - - @Test - public void test400ImportFromResource() throws Exception { - // GIVEN - checkAllShadows(); - assertNoRepoThreadLocalCache(); - - OperationResult result = createOperationResult(); - - // Make sure Mr. Gibbs has "l" attribute set to the same value as an outbound expression is setting - ChangeRecordEntry entry = openDJController.executeLdifChange(LDIF_GIBBS_MODIFY_FILE); - displayValue("Entry from LDIF", entry); - - // Let's add an entry with multiple uids. - Entry addEntry = openDJController.addEntryFromLdifFile(LDIF_HERMAN_FILENAME); - display("Entry from LDIF", addEntry); - - // WHEN - when(); - TaskType taskType = modelWeb.importFromResource(RESOURCE_OPENDJ_OID, RESOURCE_OPENDJ_ACCOUNT_OBJECTCLASS); - - // THEN - then(); - assertNoRepoThreadLocalCache(); - displayJaxb("importFromResource result", taskType.getResult(), SchemaConstants.C_RESULT); - AssertJUnit.assertEquals("importFromResource has failed", OperationResultStatusType.IN_PROGRESS, taskType.getResult().getStatus()); - // Convert the returned TaskType to a more usable Task - Task task = taskManager.createTaskInstance(taskType.asPrismObject(), result); - AssertJUnit.assertNotNull(task); - assertNotNull(task.getOid()); - AssertJUnit.assertTrue(task.isAsynchronous()); - AssertJUnit.assertEquals(TaskExecutionStatus.RUNNABLE, task.getExecutionStatus()); -// AssertJUnit.assertEquals(TaskExclusivityStatus.CLAIMED, task.getExclusivityStatus()); - - display("Import task after launch", task); - - PrismObject tObject = repositoryService.getObject(TaskType.class, task.getOid(), null, result); - TaskType taskAfter = tObject.asObjectable(); - display("Import task in repo after launch", taskAfter); - - result.computeStatus(); - TestUtil.assertSuccess("getObject has failed", result); - - final String taskOid = task.getOid(); - - waitFor("Waiting for import to complete", new Checker() { - @Override - public boolean check() throws CommonException { - Holder resultHolder = new Holder<>(); - Holder objectHolder = new Holder<>(); - OperationResult opResult = new OperationResult("import check"); - assertNoRepoThreadLocalCache(); - SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); - try { - modelWeb.getObject(ObjectTypes.TASK.getTypeQName(), taskOid, - options, objectHolder, resultHolder); - } catch (FaultMessage faultMessage) { - throw new SystemException(faultMessage); - } - assertNoRepoThreadLocalCache(); - // display("getObject result (wait loop)",resultHolder.value); - TestUtil.assertSuccess("getObject has failed", resultHolder.value); - Task task = taskManager.createTaskInstance((PrismObject) objectHolder.value.asPrismObject(), opResult); - System.out.println(new Date() + ": Import task status: " + task.getExecutionStatus() + ", progress: " + task.getProgress()); - if (task.getExecutionStatus() == TaskExecutionStatus.CLOSED) { - // Task closed, wait finished - return true; - } - // IntegrationTestTools.display("Task result while waiting: ", task.getResult()); - return false; - } - - @Override - public void timeout() { - // No reaction, the test will fail right after return from this - } - }, 180000); - - // wait a second until the task will be definitely saved - Thread.sleep(1000); - - //### Check task state after the task is finished ### - - Holder objectHolder = new Holder<>(); - Holder resultHolder = new Holder<>(); - SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); - assertNoRepoThreadLocalCache(); - - modelWeb.getObject(ObjectTypes.TASK.getTypeQName(), task.getOid(), - options, objectHolder, resultHolder); - - assertNoRepoThreadLocalCache(); - TestUtil.assertSuccess("getObject has failed", resultHolder.value); - task = taskManager.createTaskInstance((PrismObject) objectHolder.value.asPrismObject(), result); - - display("Import task after finish (fetched from model)", task); - - AssertJUnit.assertEquals(TaskExecutionStatus.CLOSED, task.getExecutionStatus()); - - assertNotNull("Null lastRunStartTimestamp in " + task, task.getLastRunStartTimestamp()); - assertNotNull("Null lastRunFinishTimestamp in " + task, task.getLastRunFinishTimestamp()); - - long importDuration = task.getLastRunFinishTimestamp() - task.getLastRunStartTimestamp(); - double usersPerSec = (task.getProgress() * 1000) / importDuration; - display("Imported " + task.getProgress() + " users in " + importDuration + " milliseconds (" + usersPerSec + " users/sec)"); - - OperationResultStatusType taskResultStatus = task.getResultStatus(); - AssertJUnit.assertNotNull("Task has no result status", taskResultStatus); - assertEquals("Import task result is not success", OperationResultStatusType.SUCCESS, taskResultStatus); - - AssertJUnit.assertTrue("No progress", task.getProgress() > 0); - - //### Check if the import created users and shadows ### - - // Listing of shadows is not supported by the provisioning. So we need - // to look directly into repository - List> sobjects = repositoryService.searchObjects(ShadowType.class, null, null, result); - result.computeStatus(); - TestUtil.assertSuccess("listObjects has failed", result); - AssertJUnit.assertFalse("No shadows created", sobjects.isEmpty()); - - for (PrismObject aObject : sobjects) { - ShadowType shadow = aObject.asObjectable(); - display("Shadow object after import (repo)", shadow); - assertNotEmpty("No OID in shadow", shadow.getOid()); // This would be really strange ;-) - assertNotEmpty("No name in shadow", shadow.getName()); - AssertJUnit.assertNotNull("No objectclass in shadow", shadow.getObjectClass()); - AssertJUnit.assertNotNull("Null attributes in shadow", shadow.getAttributes()); - String resourceOid = shadow.getResourceRef().getOid(); - if (resourceOid.equals(RESOURCE_OPENDJ_OID)) { - assertAttributeNotNull("No identifier in shadow", shadow, getOpenDjPrimaryIdentifierQName()); - } else { - assertAttributeNotNull("No UID in shadow", shadow, SchemaConstants.ICFS_UID); - } - } - - Holder listHolder = new Holder<>(); - assertNoRepoThreadLocalCache(); - - modelWeb.searchObjects(ObjectTypes.USER.getTypeQName(), null, null, - listHolder, resultHolder); - - assertNoRepoThreadLocalCache(); - ObjectListType uobjects = listHolder.value; - TestUtil.assertSuccess("listObjects has failed", resultHolder.value); - AssertJUnit.assertFalse("No users created", uobjects.getObject().isEmpty()); - - // TODO: use another account, not guybrush - - display("Users after import " + uobjects.getObject().size()); - - for (ObjectType oo : uobjects.getObject()) { - UserType user = (UserType) oo; - if (SystemObjectsType.USER_ADMINISTRATOR.value().equals(user.getOid())) { - //skip administrator check - continue; - } - display("User after import (repo)", user); - assertNotEmpty("No OID in user", user.getOid()); // This would be - // really - // strange ;-) - assertNotEmpty("No name in user", user.getName()); - assertNotNull("No fullName in user", user.getFullName()); - assertNotEmpty("No fullName in user", user.getFullName().getOrig()); - assertNotEmpty("No familyName in user", user.getFamilyName().getOrig()); - // givenName is not mandatory in LDAP, therefore givenName may not - // be present on user - - if (user.getName().getOrig().equals(USER_GUYBRUSH_USERNAME)) { - // skip the rest of checks for guybrush, he does not have LDAP account now - continue; - } - - assertTrue("User " + user.getName() + " is disabled (" + user.getActivation().getAdministrativeStatus() + ")", user.getActivation() == null || - user.getActivation().getAdministrativeStatus() == ActivationStatusType.ENABLED); - - List accountRefs = user.getLinkRef(); - AssertJUnit.assertEquals("Wrong accountRef for user " + user.getName(), 1, accountRefs.size()); - ObjectReferenceType accountRef = accountRefs.get(0); - - boolean found = false; - for (PrismObject aObject : sobjects) { - ShadowType acc = aObject.asObjectable(); - if (accountRef.getOid().equals(acc.getOid())) { - found = true; - break; - } - } - if (!found) { - AssertJUnit.fail("accountRef does not point to existing account " + accountRef.getOid()); - } - - PrismObject aObject = modelService.getObject(ShadowType.class, accountRef.getOid(), null, task, result); - ShadowType account = aObject.asObjectable(); - - display("Account after import ", account); - - String attributeValueL = ShadowUtil.getMultiStringAttributeValueAsSingle(account, - new QName(ResourceTypeUtil.getResourceNamespace(resourceTypeOpenDjrepo), "l")); -// assertEquals("Unexcpected value of l", "middle of nowhere", attributeValueL); - assertEquals("Unexcpected value of l", getUserLocality(user), attributeValueL); - } - - // This also includes "idm" user imported from LDAP. Later we need to ignore that one. - assertEquals("Wrong number of users after import", 10, uobjects.getObject().size()); - - checkAllShadows(); - - } - - private String getUserLocality(UserType user) { - return user.getLocality() != null ? user.getLocality().getOrig() : "middle of nowhere"; - } - - @Test - public void test420RecomputeUsers() throws Exception { - // GIVEN - - final OperationResult result = createOperationResult(); - - // Assign role to a user, but we do this using a repository instead of model. - // The role assignment will not be executed and this created an inconsistent state. - ObjectDeltaType changeAddRoleCaptain = unmarshalValueFromFile( - REQUEST_USER_MODIFY_ADD_ROLE_CAPTAIN_1_FILENAME, ObjectDeltaType.class); - Collection modifications = DeltaConvertor.toModifications(changeAddRoleCaptain.getItemDelta(), - getUserDefinition()); - repositoryService.modifyObject(UserType.class, changeAddRoleCaptain.getOid(), modifications, result); - - // TODO: setup more "inconsistent" state - - // Add reconciliation task. This will trigger reconciliation - - importObjectFromFile(TASK_USER_RECOMPUTE_FILENAME, result); - - // We need to wait for a sync interval, so the task scanner has a chance - // to pick up this - // task - - waitFor("Waiting for task to finish", new Checker() { - public boolean check() throws ObjectNotFoundException, SchemaException { - Task task = taskManager.getTaskPlain(TASK_USER_RECOMPUTE_OID, result); - //display("Task while waiting for task manager to pick up the task", task); - // wait until the task is finished - if (TaskExecutionStatus.CLOSED == task.getExecutionStatus()) { - return true; - } - return false; - } - - @Override - public void timeout() { - // No reaction, the test will fail right after return from this - } - }, 40000); - - // wait a second until the task will be definitely saved - Thread.sleep(1000); - - // Check task status - - Task task = taskManager.getTaskWithResult(TASK_USER_RECOMPUTE_OID, result); - result.computeStatus(); - display("getTask result", result); - TestUtil.assertSuccess("getTask has failed", result); - AssertJUnit.assertNotNull(task); - display("Task after finish", task); - AssertJUnit.assertNotNull(task.getTaskIdentifier()); - assertFalse(task.getTaskIdentifier().isEmpty()); - - PrismObject o = repositoryService.getObject(TaskType.class, TASK_USER_RECOMPUTE_OID, null, result); - display("Task after pickup in the repository", o.asObjectable()); - - AssertJUnit.assertEquals(TaskExecutionStatus.CLOSED, task.getExecutionStatus()); - - // .. and last run should not be zero - assertNotNull(task.getLastRunStartTimestamp()); - AssertJUnit.assertFalse(task.getLastRunStartTimestamp().longValue() == 0); - assertNotNull(task.getLastRunFinishTimestamp()); - AssertJUnit.assertFalse(task.getLastRunFinishTimestamp().longValue() == 0); - - AssertJUnit.assertEquals(10, task.getProgress()); - - // Test for presence of a result. It should be there and it should - // indicate success - OperationResult taskResult = task.getResult(); - display("Recompute task result", taskResult); - AssertJUnit.assertNotNull(taskResult); - TestUtil.assertSuccess("Recompute task result", taskResult); - - // STOP the task. We don't need it any more and we don't want to give it a chance to run more than once - taskManager.deleteTask(TASK_USER_RECOMPUTE_OID, result); - - // CHECK RESULT: account created for user guybrush - - // Check if user object was modified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - - PrismObject object = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); - UserType repoUser = object.asObjectable(); - - repoResult.computeStatus(); - displayJaxb("User (repository)", repoUser, new QName("user")); - - List accountRefs = repoUser.getLinkRef(); - assertEquals("Wrong number of accountRefs after recompute for user " + repoUser.getName(), 1, accountRefs.size()); - ObjectReferenceType accountRef = accountRefs.get(0); - accountShadowOidGuybrushOpendj = accountRef.getOid(); - assertFalse(accountShadowOidGuybrushOpendj.isEmpty()); - - // Check if shadow was created in the repo - - repoResult = new OperationResult("getObject"); - - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, - null, repoResult); - ShadowType repoShadowType = repoShadow.asObjectable(); - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject has failed", repoResult); - displayJaxb("Shadow (repository)", repoShadowType, new QName("shadow")); - assertNotNull(repoShadowType); - assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); - - accountGuybrushOpendjEntryUuuid = checkRepoShadow(repoShadow); - - // check if account was created in LDAP - - Entry entry = openDJController.searchAndAssertByEntryUuid(accountGuybrushOpendjEntryUuuid); - - display("LDAP account", entry); - - OpenDJController.assertAttribute(entry, "uid", "guybrush"); - OpenDJController.assertAttribute(entry, "givenName", "Guybrush"); - OpenDJController.assertAttribute(entry, "sn", "Threepwood"); - OpenDJController.assertAttribute(entry, "cn", "Guybrush Threepwood"); - OpenDJController.assertAttribute(entry, "displayName", "Guybrush Threepwood"); - // The "l" attribute is assigned indirectly through schemaHandling and - // config object - OpenDJController.assertAttribute(entry, "l", "Deep in the Caribbean"); - - // Set by the role - OpenDJController.assertAttribute(entry, "employeeType", "sailor"); - OpenDJController.assertAttribute(entry, "title", "Honorable Captain"); - OpenDJController.assertAttribute(entry, "carLicense", "C4PT41N"); - OpenDJController.assertAttribute(entry, "businessCategory", "cruise"); - - String guybrushPassword = OpenDJController.getAttributeValue(entry, "userPassword"); - assertNotNull("Pasword was not set on create", guybrushPassword); - - checkAllShadows(); - } - - @Test - public void test440ReconcileResourceOpenDj() throws Exception { - // GIVEN - - final OperationResult result = createOperationResult(); - - // Create LDAP account without an owner. The liveSync is off, so it will not be picked up - - Entry ldifEntry = openDJController.addEntryFromLdifFile(LDIF_ELAINE_FILENAME); - display("Entry from LDIF", ldifEntry); - - // Guybrush's attributes were set up by a role in the previous test. Let's mess the up a bit. Recon should sort it out. - - List modifications = new ArrayList<>(); - // Expect that a correct title will be added to this one - RawModification titleMod = RawModification.create(ModificationType.REPLACE, "title", "Scurvy earthworm"); - modifications.add(titleMod); - // Expect that the correct location will replace this one - RawModification lMod = RawModification.create(ModificationType.REPLACE, "l", "Davie Jones' locker"); - modifications.add(lMod); - // Expect that this will be untouched - RawModification poMod = RawModification.create(ModificationType.REPLACE, "postOfficeBox", "X marks the spot"); - modifications.add(poMod); - ModifyOperation modifyOperation = openDJController.getInternalConnection().processModify(USER_GUYBRUSH_LDAP_DN, modifications); - if (ResultCode.SUCCESS != modifyOperation.getResultCode()) { - AssertJUnit.fail("LDAP operation failed: " + modifyOperation.getErrorMessage()); - } - - // TODO: setup more "inconsistent" state - - // Add reconciliation task. This will trigger reconciliation - - repoAddObjectFromFile(TASK_OPENDJ_RECON_FILENAME, result); - - // We need to wait for a sync interval, so the task scanner has a chance - // to pick up this - // task - - waitFor("Waiting for task to finish first run", new Checker() { - public boolean check() throws ObjectNotFoundException, SchemaException { - Task task = taskManager.getTaskPlain(TASK_OPENDJ_RECON_OID, result); - display("Task while waiting for task manager to pick up the task", task); - // wait until the task is finished - return task.getLastRunFinishTimestamp() != null; - } - - @Override - public void timeout() { - // No reaction, the test will fail right after return from this - } - }, 180000); - - // Check task status - - Task task = taskManager.getTaskPlain(TASK_OPENDJ_RECON_OID, result); - result.computeStatus(); - display("getTask result", result); - TestUtil.assertSuccess("getTask has failed", result); - AssertJUnit.assertNotNull(task); - display("Task after pickup", task); - - PrismObject o = repositoryService.getObject(TaskType.class, TASK_OPENDJ_RECON_OID, null, result); - display("Task after pickup in the repository", o.asObjectable()); - - // .. it should be running - AssertJUnit.assertEquals(TaskExecutionStatus.RUNNABLE, task.getExecutionStatus()); - - // .. and claimed -// AssertJUnit.assertEquals(TaskExclusivityStatus.CLAIMED, task.getExclusivityStatus()); - - // .. and last run should not be zero - assertNotNull("Null last run start in recon task", task.getLastRunStartTimestamp()); - AssertJUnit.assertFalse("Zero last run start in recon task", task.getLastRunStartTimestamp().longValue() == 0); - assertNotNull("Null last run finish in recon task", task.getLastRunFinishTimestamp()); - AssertJUnit.assertFalse("Zero last run finish in recon task", task.getLastRunFinishTimestamp().longValue() == 0); - - // The progress should be 0, as there were no changes yet - // [pm] commented out, as progress in recon task is now determined not only using # of changes - //AssertJUnit.assertEquals(0, task.getProgress()); - - // Test for presence of a result. It was not fetched - so it should NOT be there - OperationResult taskResult = task.getResult(); - AssertJUnit.assertNull(taskResult); - - // However, the task should indicate success - AssertJUnit.assertEquals(OperationResultStatusType.SUCCESS, task.getResultStatus()); - - // STOP the task. We don't need it any more and we don't want to give it a chance to run more than once - taskManager.deleteTask(TASK_OPENDJ_RECON_OID, result); - - // CHECK RESULT: account for user guybrush should be still there and unchanged - - // Check if user object was modified in the repo - - OperationResult repoResult = new OperationResult("getObject"); - - PrismObject uObject = repositoryService.getObject(UserType.class, USER_GUYBRUSH_OID, null, repoResult); - UserType repoUser = uObject.asObjectable(); - repoResult.computeStatus(); - displayJaxb("User (repository)", repoUser, new QName("user")); - - List accountRefs = repoUser.getLinkRef(); - assertEquals("Guybrush has wrong number of accounts", 1, accountRefs.size()); - ObjectReferenceType accountRef = accountRefs.get(0); - accountShadowOidGuybrushOpendj = accountRef.getOid(); - assertFalse(accountShadowOidGuybrushOpendj.isEmpty()); - - // Check if shadow was created in the repo - - repoResult = new OperationResult("getObject"); - - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidGuybrushOpendj, - null, repoResult); - ShadowType repoShadowType = repoShadow.asObjectable(); - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject has failed", repoResult); - displayJaxb("Shadow (repository)", repoShadowType, new QName("shadow")); - assertNotNull(repoShadowType); - assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); - - accountGuybrushOpendjEntryUuuid = checkRepoShadow(repoShadow); - - // check if account was created in LDAP - - Entry entry = openDJController.searchAndAssertByEntryUuid(accountGuybrushOpendjEntryUuuid); - - display("LDAP account", entry); - - OpenDJController.assertAttribute(entry, "uid", "guybrush"); - OpenDJController.assertAttribute(entry, "givenName", "Guybrush"); - OpenDJController.assertAttribute(entry, "sn", "Threepwood"); - OpenDJController.assertAttribute(entry, "cn", "Guybrush Threepwood"); - OpenDJController.assertAttribute(entry, "displayName", "Guybrush Threepwood"); - // The "l" attribute is assigned indirectly through schemaHandling and - // config object. It is not tolerant, therefore the other value should be gone now - OpenDJController.assertAttribute(entry, "l", "Deep in the Caribbean"); - - // Set by the role - OpenDJController.assertAttribute(entry, "employeeType", "sailor"); - - // "title" is tolerant, so it will retain the original value as well as the one provided by the role - OpenDJController.assertAttribute(entry, "title", "Scurvy earthworm", "Honorable Captain"); - - OpenDJController.assertAttribute(entry, "carLicense", "C4PT41N"); - OpenDJController.assertAttribute(entry, "businessCategory", "cruise"); - - // No setting for "postOfficeBox", so the value should be unchanged - OpenDJController.assertAttribute(entry, "postOfficeBox", "X marks the spot"); - - String guybrushPassword = OpenDJController.getAttributeValue(entry, "userPassword"); - assertNotNull("Pasword was not set on create", guybrushPassword); - -// QueryType query = QueryUtil.createNameQuery(ELAINE_NAME); -// ObjectQuery query = ObjectQuery.createObjectQuery(EqualsFilter.createEqual(UserType.class, prismContext, UserType.F_NAME, ELAINE_NAME)); - ObjectQuery query = ObjectQueryUtil.createNameQuery(ELAINE_NAME, prismContext); - List> users = repositoryService.searchObjects(UserType.class, query, null, repoResult); - assertEquals("Wrong number of Elaines", 1, users.size()); - repoUser = users.get(0).asObjectable(); - - repoResult.computeStatus(); - displayJaxb("User Elaine (repository)", repoUser, new QName("user")); - - assertNotNull(repoUser.getOid()); - assertEquals(PrismTestUtil.createPolyStringType(ELAINE_NAME), repoUser.getName()); - PrismAsserts.assertEqualsPolyString("wrong repo givenName", "Elaine", repoUser.getGivenName()); - PrismAsserts.assertEqualsPolyString("wrong repo familyName", "Marley", repoUser.getFamilyName()); - PrismAsserts.assertEqualsPolyString("wrong repo fullName", "Elaine Marley", repoUser.getFullName()); - - accountRefs = repoUser.getLinkRef(); - assertEquals("Elaine has wrong number of accounts", 1, accountRefs.size()); - accountRef = accountRefs.get(0); - String accountShadowOidElaineOpendj = accountRef.getOid(); - assertFalse(accountShadowOidElaineOpendj.isEmpty()); - - // Check if shadow was created in the repo - - repoResult = new OperationResult("getObject"); - - repoShadow = repositoryService.getObject(ShadowType.class, accountShadowOidElaineOpendj, - null, repoResult); - repoShadowType = repoShadow.asObjectable(); - repoResult.computeStatus(); - TestUtil.assertSuccess("getObject has failed", repoResult); - displayJaxb("Shadow (repository)", repoShadowType, new QName("shadow")); - assertNotNull(repoShadowType); - assertEquals(RESOURCE_OPENDJ_OID, repoShadowType.getResourceRef().getOid()); - - String accountElainehOpendjEntryUuuid = checkRepoShadow(repoShadow); - - // check if account is still in LDAP - - entry = openDJController.searchAndAssertByEntryUuid(accountElainehOpendjEntryUuuid); - - display("LDAP account", entry); - - OpenDJController.assertAttribute(entry, "uid", ELAINE_NAME); - OpenDJController.assertAttribute(entry, "givenName", "Elaine"); - OpenDJController.assertAttribute(entry, "sn", "Marley"); - OpenDJController.assertAttribute(entry, "cn", "Elaine Marley"); - OpenDJController.assertAttribute(entry, "displayName", "Elaine Marley"); - // The "l" attribute is assigned indirectly through schemaHandling and - // config object - // FIXME - //OpenDJController.assertAttribute(entry, "l", "middle of nowhere"); - - // Set by the role - OpenDJController.assertAttribute(entry, "employeeType", "governor"); - OpenDJController.assertAttribute(entry, "title", "Governor"); - OpenDJController.assertAttribute(entry, "businessCategory", "state"); - - String elainePassword = OpenDJController.getAttributeValue(entry, "userPassword"); - assertNotNull("Password of Elaine has disappeared", elainePassword); - - checkAllShadows(); - } - - @Test - public void test480ListResources() throws Exception { - // GIVEN - OperationResultType result = new OperationResultType(); - Holder resultHolder = new Holder<>(result); - - Holder objectListHolder = new Holder<>(); - SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); - - // WHEN - modelWeb.searchObjects(ObjectTypes.RESOURCE.getTypeQName(), null, options, objectListHolder, resultHolder); - - // THEN - - displayValue("Resources", objectListHolder.value); - assertEquals("Unexpected number of resources", 4, objectListHolder.value.getObject().size()); - // TODO - - for (ObjectType object : objectListHolder.value.getObject()) { - // Marshalling may fail even though the Java object is OK so test for it - String xml = prismContext.xmlSerializer().serialize(object.asPrismObject()); - } - - } - - @Test - public void test485ListResourcesWithBrokenResource() throws Exception { - // GIVEN - Task task = getTestTask(); - final OperationResult result = getTestOperationResult(); - - // WHEN - List> resources = modelService.searchObjects(ResourceType.class, null, null, task, result); - - // THEN - assertNotNull("listObjects returned null list", resources); - - for (PrismObject object : resources) { - ResourceType resource = object.asObjectable(); - //display("Resource found",resource); - display("Found " + ObjectTypeUtil.toShortString(resource) + ", result " + (resource.getFetchResult() == null ? "null" : resource.getFetchResult().getStatus())); - - assertNotNull(resource.getOid()); - assertNotNull(resource.getName()); - - if (resource.getOid().equals(RESOURCE_BROKEN_OID)) { - assertTrue("No error in fetchResult in " + ObjectTypeUtil.toShortString(resource), - resource.getFetchResult() != null && - (resource.getFetchResult().getStatus() == OperationResultStatusType.PARTIAL_ERROR || - resource.getFetchResult().getStatus() == OperationResultStatusType.FATAL_ERROR)); - } else { - assertTrue("Unexpected error in fetchResult in " + ObjectTypeUtil.toShortString(resource), - resource.getFetchResult() == null || resource.getFetchResult().getStatus() == OperationResultStatusType.SUCCESS); - } - } - } - - @Test - public void test500NotifyChangeCreateAccount() throws Exception { - Entry ldifEntry = openDJController.addEntryFromLdifFile(LDIF_ANGELIKA_FILENAME); - display("Entry from LDIF", ldifEntry); - - List attributes = ldifEntry.getAttributes(); - List attrs = ldifEntry.getAttribute("entryUUID"); - - AttributeValue val = null; - if (attrs == null) { - for (Attribute a : attributes) { - if (a.getName().equals("entryUUID")) { - val = a.iterator().next(); - } - } - } else { - val = attrs.get(0).iterator().next(); - } - - String entryUuid = val.toString(); - - ShadowType anglicaAccount = parseObjectType(new File(ACCOUNT_ANGELIKA_FILENAME), ShadowType.class); - PrismProperty prop = anglicaAccount.asPrismObject().findContainer(ShadowType.F_ATTRIBUTES).getValue().createProperty( - prismContext.definitionFactory().createPropertyDefinition(getOpenDjPrimaryIdentifierQName(), DOMUtil.XSD_STRING)); - prop.setRealValue(entryUuid); - anglicaAccount.setResourceRef(ObjectTypeUtil.createObjectRef(RESOURCE_OPENDJ_OID, ObjectTypes.RESOURCE)); - - displayValue("Angelica shadow: ", anglicaAccount.asPrismObject().debugDump()); - - ResourceObjectShadowChangeDescriptionType changeDescription = new ResourceObjectShadowChangeDescriptionType(); - ObjectDeltaType delta = new ObjectDeltaType(); - delta.setChangeType(ChangeTypeType.ADD); - delta.setObjectToAdd(anglicaAccount); - delta.setObjectType(ShadowType.COMPLEX_TYPE); - changeDescription.setObjectDelta(delta); - changeDescription.setChannel(SchemaConstants.CHANNEL_WEB_SERVICE_URI); - - // WHEN - TaskType task = modelWeb.notifyChange(changeDescription); - - // THEN - OperationResult result = OperationResult.createOperationResult(task.getResult()); - display(result); - assertSuccess(result); - - PrismObject userAngelika = findUserByUsername(ANGELIKA_NAME); - assertNotNull("User with the name angelika must exist.", userAngelika); - - UserType user = userAngelika.asObjectable(); - assertNotNull("User with the name angelika must have one link ref.", user.getLinkRef()); - - assertEquals("Expected one account ref in user", 1, user.getLinkRef().size()); - String oid = user.getLinkRef().get(0).getOid(); - - PrismObject modelShadow = modelService.getObject(ShadowType.class, oid, null, taskManager.createTaskInstance(), result); - - assertAttributeNotNull(modelShadow, getOpenDjPrimaryIdentifierQName()); - assertAttribute(modelShadow, "uid", "angelika"); - assertAttribute(modelShadow, "givenName", "Angelika"); - assertAttribute(modelShadow, "sn", "Marley"); - assertAttribute(modelShadow, "cn", "Angelika Marley"); - - } - - @Test - public void test501NotifyChangeModifyAccount() throws Exception { - PrismObject userAngelika = findUserByUsername(ANGELIKA_NAME); - assertNotNull("User with the name angelika must exist.", userAngelika); - - UserType user = userAngelika.asObjectable(); - assertNotNull("User with the name angelika must have one link ref.", user.getLinkRef()); - - assertEquals("Expected one account ref in user", 1, user.getLinkRef().size()); - String oid = user.getLinkRef().get(0).getOid(); - - ResourceObjectShadowChangeDescriptionType changeDescription = new ResourceObjectShadowChangeDescriptionType(); - ObjectDeltaType delta = new ObjectDeltaType(); - delta.setChangeType(ChangeTypeType.MODIFY); - delta.setObjectType(ShadowType.COMPLEX_TYPE); - - ItemDeltaType mod1 = new ItemDeltaType(); - mod1.setModificationType(ModificationTypeType.REPLACE); - ItemPathType path = new ItemPathType(ItemPath.create(ShadowType.F_ATTRIBUTES, new QName(resourceTypeOpenDjrepo.getNamespace(), "givenName"))); - mod1.setPath(path); - - RawType value = new RawType(prismContext.xnodeFactory().primitive("newAngelika"), prismContext); - mod1.getValue().add(value); - - delta.getItemDelta().add(mod1); - delta.setOid(oid); - - logger.info("item delta: {}", SchemaDebugUtil.prettyPrint(mod1)); - - logger.info("delta: {}", DebugUtil.dump(mod1)); - - changeDescription.setObjectDelta(delta); - - changeDescription.setOldShadowOid(oid); - changeDescription.setChannel(SchemaConstants.CHANNEL_WEB_SERVICE_URI); - - // WHEN - TaskType task = modelWeb.notifyChange(changeDescription); - - // THEN - OperationResult result = OperationResult.createOperationResult(task.getResult()); - display(result); - assertSuccess(result); - - PrismObject userAngelikaAfterSync = findUserByUsername(ANGELIKA_NAME); - assertNotNull("User with the name angelika must exist.", userAngelikaAfterSync); - - UserType userAfterSync = userAngelikaAfterSync.asObjectable(); - - PrismAsserts.assertEqualsPolyString("wrong given name in user angelika", PrismTestUtil.createPolyStringType("newAngelika"), userAfterSync.getGivenName()); - - } - - @Test - public void test502NotifyChangeModifyAccountPassword() throws Exception { - PrismObject userAngelika = findUserByUsername(ANGELIKA_NAME); - assertNotNull("User with the name angelika must exist.", userAngelika); - - UserType user = userAngelika.asObjectable(); - assertNotNull("User with the name angelika must have one link ref.", user.getLinkRef()); - - assertEquals("Expected one account ref in user", 1, user.getLinkRef().size()); - String oid = user.getLinkRef().get(0).getOid(); - - String newPassword = "newPassword"; - - openDJController.modifyReplace("uid=" + ANGELIKA_NAME + "," + openDJController.getSuffixPeople(), "userPassword", newPassword); - - ResourceObjectShadowChangeDescriptionType changeDescription = new ResourceObjectShadowChangeDescriptionType(); - ObjectDeltaType delta = new ObjectDeltaType(); - delta.setChangeType(ChangeTypeType.MODIFY); - delta.setObjectType(ShadowType.COMPLEX_TYPE); - - ItemDeltaType passwordDelta = new ItemDeltaType(); - passwordDelta.setModificationType(ModificationTypeType.REPLACE); - passwordDelta.setPath(ModelClientUtil.createItemPathType("credentials/password/value", prismContext)); - RawType passwordValue = new RawType(prismContext.xnodeSerializer().root(new QName("dummy")).serializeRealValue(ModelClientUtil.createProtectedString(newPassword)).getSubnode(), prismContext); - passwordDelta.getValue().add(passwordValue); - - delta.getItemDelta().add(passwordDelta); - delta.setOid(oid); - - logger.info("item delta: {}", SchemaDebugUtil.prettyPrint(passwordDelta)); - - logger.info("delta: {}", DebugUtil.dump(passwordDelta)); - - changeDescription.setObjectDelta(delta); - - changeDescription.setOldShadowOid(oid); -// changeDescription.setCurrentShadow(angelicaShadowType); - changeDescription.setChannel(SchemaConstants.CHANNEL_WEB_SERVICE_URI); - - // WHEN - TaskType task = modelWeb.notifyChange(changeDescription); - - // THEN - OperationResult result = OperationResult.createOperationResult(task.getResult()); - display(result); - assertSuccess(result); - - PrismObject userAngelikaAfterSync = findUserByUsername(ANGELIKA_NAME); - assertNotNull("User with the name angelika must exist.", userAngelikaAfterSync); - - assertUserLdapPassword(userAngelikaAfterSync, newPassword); - - } - - @Test - public void test503NotifyChangeDeleteAccount() throws Exception { - PrismObject userAngelika = findUserByUsername(ANGELIKA_NAME); - assertNotNull("User with the name angelika must exist.", userAngelika); - - UserType user = userAngelika.asObjectable(); - assertNotNull("User with the name angelika must have one link ref.", user.getLinkRef()); - - assertEquals("Expected one account ref in user", 1, user.getLinkRef().size()); - String oid = user.getLinkRef().get(0).getOid(); - - ResourceObjectShadowChangeDescriptionType changeDescription = new ResourceObjectShadowChangeDescriptionType(); - ObjectDeltaType delta = new ObjectDeltaType(); - delta.setChangeType(ChangeTypeType.DELETE); - delta.setObjectType(ShadowType.COMPLEX_TYPE); - delta.setOid(oid); - changeDescription.setObjectDelta(delta); - changeDescription.setOldShadowOid(oid); - changeDescription.setChannel(SchemaConstants.CHANNEL_WEB_SERVICE_URI); - - // WHEN - TaskType task = modelWeb.notifyChange(changeDescription); - - // THEN - OperationResult result = OperationResult.createOperationResult(task.getResult()); - display(result); - assertTrue(result.isAcceptable()); - - PrismObject userAngelikaAfterSync = findUserByUsername(ANGELIKA_NAME); - display("User after", userAngelikaAfterSync); - assertNotNull("User with the name angelika must exist.", userAngelikaAfterSync); - - UserType userType = userAngelikaAfterSync.asObjectable(); - assertNotNull("User with the name angelika must have one link ref.", userType.getLinkRef()); - - assertEquals("Expected no account ref in user", 0, userType.getLinkRef().size()); - - } - - @Test - public void test999Shutdown() throws Exception { - taskManager.shutdown(); - waitFor("waiting for task manager shutdown", new Checker() { - @Override - public boolean check() { - return taskManager.getLocallyRunningTasks(new OperationResult("dummy")).isEmpty(); - } - - @Override - public void timeout() { - // No reaction, the test will fail right after return from this - } - }, 10000); - AssertJUnit.assertEquals("Some tasks left running after shutdown", new HashSet(), - new HashSet<>(taskManager.getLocallyRunningTasks(new OperationResult("dummy")))); - } - - // TODO: test for missing/corrupt system configuration - // TODO: test for missing sample config (bad reference in expression - // arguments) - - private String checkRepoShadow(PrismObject repoShadow) { - ShadowType repoShadowType = repoShadow.asObjectable(); - String uid = null; - boolean hasOthers = false; - List xmlAttributes = repoShadowType.getAttributes().getAny(); - for (Object element : xmlAttributes) { - if (SchemaConstants.ICFS_UID.equals(JAXBUtil.getElementQName(element)) || getOpenDjPrimaryIdentifierQName().equals(JAXBUtil.getElementQName(element))) { - if (uid != null) { - AssertJUnit.fail("Multiple values for ICF UID in shadow attributes"); - } else { - uid = ((Element) element).getTextContent(); - } - } else if (SchemaConstants.ICFS_NAME.equals(JAXBUtil.getElementQName(element)) || getOpenDjSecondaryIdentifierQName().equals(JAXBUtil.getElementQName(element))) { - // This is OK - } else { - hasOthers = true; - } - } - - assertFalse("Shadow " + repoShadow + " has unexpected elements", hasOthers); - assertNotNull(uid); - - return uid; - } - - private QName getOpenDjPrimaryIdentifierQName() { - return new QName(RESOURCE_OPENDJ_NS, RESOURCE_OPENDJ_PRIMARY_IDENTIFIER_LOCAL_NAME); - } - - private QName getOpenDjSecondaryIdentifierQName() { - return new QName(RESOURCE_OPENDJ_NS, RESOURCE_OPENDJ_SECONDARY_IDENTIFIER_LOCAL_NAME); - } - - private ShadowType searchAccountByOid(final String accountOid) throws Exception { - OperationResultType resultType = new OperationResultType(); - Holder resultHolder = new Holder<>(resultType); - Holder accountHolder = new Holder<>(); - SelectorQualifiedGetOptionsType options = new SelectorQualifiedGetOptionsType(); - modelWeb.getObject(ObjectTypes.SHADOW.getTypeQName(), accountOid, options, accountHolder, resultHolder); - ObjectType object = accountHolder.value; - TestUtil.assertSuccess("searchObjects has failed", resultHolder.value); - assertNotNull("Account is null", object); - - if (!(object instanceof ShadowType)) { - fail("Object is not account."); - } - ShadowType account = (ShadowType) object; - assertEquals(accountOid, account.getOid()); - - return account; - } - - private UserType searchUserByName(String name) throws Exception { -// Document doc = DOMUtil.getDocument(); -// Element nameElement = doc.createElementNS(SchemaConstants.C_NAME.getNamespaceURI(), -// SchemaConstants.C_NAME.getLocalPart()); -// nameElement.setTextContent(name); -// Element filter = QueryUtil.createEqualFilter(doc, null, nameElement); -// -// QueryType query = new QueryType(); -// query.setFilter(filter); - ObjectQuery q = ObjectQueryUtil.createNameQuery(UserType.class, prismContext, name); - QueryType query = prismContext.getQueryConverter().createQueryType(q); - OperationResultType resultType = new OperationResultType(); - Holder resultHolder = new Holder<>(resultType); - Holder listHolder = new Holder<>(); - assertNoRepoThreadLocalCache(); - - modelWeb.searchObjects(ObjectTypes.USER.getTypeQName(), query, null, listHolder, resultHolder); - - assertNoRepoThreadLocalCache(); - ObjectListType objects = listHolder.value; - TestUtil.assertSuccess("searchObjects has failed", resultHolder.value); - AssertJUnit.assertEquals("User not found (or found too many)", 1, objects.getObject().size()); - UserType user = (UserType) objects.getObject().get(0); - - AssertJUnit.assertEquals(user.getName(), PrismTestUtil.createPolyStringType(name)); - - return user; - } - - private void basicWaitForSyncChangeDetection(Task syncCycle, Object tokenBefore, int increment, - final OperationResult result) throws Exception { - basicWaitForSyncChangeDetection(syncCycle, (int) ((Integer) tokenBefore), increment, result); - } - - private void basicWaitForSyncChangeDetection(Task syncCycle, int tokenBefore, int increment, - final OperationResult result) throws Exception { - basicWaitForSyncChangeDetection(syncCycle, tokenBefore, increment, result, 40000); - } - - private void basicWaitForSyncChangeDetection(final Task syncCycle, final int tokenBefore, final int increment, - final OperationResult result, int timeout) throws Exception { - - waitFor("Waiting for sync cycle to detect change", new Checker() { - @Override - public boolean check() throws CommonException { - syncCycle.refresh(result); - display("SyncCycle while waiting for sync cycle to detect change", syncCycle); - if (syncCycle.getExecutionStatus() != TaskExecutionStatus.RUNNABLE) { - throw new IllegalStateException("Task not runnable: " + syncCycle.getExecutionStatus() + "; " + syncCycle); - } - int tokenNow = findSyncToken(syncCycle); - display("tokenNow = " + tokenNow); - - return tokenNow >= tokenBefore + increment; - } - - @Override - public void timeout() { - // No reaction, the test will fail right after return from this - } - }, timeout, WAIT_FOR_LOOP_SLEEP_MILLIS); - } - - private void setAssignmentEnforcement(AssignmentPolicyEnforcementType enforcementType) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException { - assumeAssignmentPolicy(enforcementType); - } - - private void assertSyncSettingsAssignmentPolicyEnforcement(AssignmentPolicyEnforcementType assignmentPolicy) throws - ObjectNotFoundException, SchemaException { - OperationResult result = new OperationResult("Asserting sync settings"); - PrismObject systemConfigurationType = repositoryService.getObject(SystemConfigurationType.class, - SystemObjectsType.SYSTEM_CONFIGURATION.value(), null, result); - result.computeStatus(); - TestUtil.assertSuccess("Asserting sync settings failed (result)", result); - ProjectionPolicyType globalAccountSynchronizationSettings = systemConfigurationType.asObjectable().getGlobalAccountSynchronizationSettings(); - assertNotNull("globalAccountSynchronizationSettings is null", globalAccountSynchronizationSettings); - AssignmentPolicyEnforcementType assignmentPolicyEnforcement = globalAccountSynchronizationSettings.getAssignmentPolicyEnforcement(); - assertNotNull("assignmentPolicyEnforcement is null", assignmentPolicyEnforcement); - assertEquals("Assignment policy mismatch", assignmentPolicy, assignmentPolicyEnforcement); - } - - private void checkAllShadows() throws SchemaException { - logger.trace("Checking all shadows"); - System.out.println("Checking all shadows"); - ObjectChecker checker = null; - IntegrationTestTools.checkAllShadows(resourceTypeOpenDjrepo, repositoryService, checker, prismContext); - } - - public static String getNormalizedAttributeValue(ShadowType repoShadow, RefinedObjectClassDefinition objClassDef, QName name) { - - String value = getAttributeValue(repoShadow, name); - - RefinedAttributeDefinition idDef = objClassDef.getPrimaryIdentifiers().iterator().next(); - if (idDef.getMatchingRuleQName() != null && idDef.getMatchingRuleQName().equals(PrismConstants.STRING_IGNORE_CASE_MATCHING_RULE_NAME)) { - return value.toLowerCase(); - } - - return value; - } - - protected void assertAttribute(ShadowType shadowType, String attrName, T... expectedValues) { - assertAttribute(resourceTypeOpenDjrepo, shadowType, attrName, expectedValues); - } - - protected void assertAttribute(PrismObject shadow, String attrName, T... expectedValues) { - assertAttribute(resourceTypeOpenDjrepo, shadow.asObjectable(), attrName, expectedValues); - } -} diff --git a/testing/sanity/src/test/resources/ctx-sanity-test-main.xml b/testing/sanity/src/test/resources/ctx-sanity-test-main.xml deleted file mode 100644 index 8557e4eee3e..00000000000 --- a/testing/sanity/src/test/resources/ctx-sanity-test-main.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/testing/sanity/src/test/resources/ctx-sanity-test.xml b/testing/sanity/src/test/resources/ctx-sanity-test.xml deleted file mode 100644 index 362551f6d33..00000000000 --- a/testing/sanity/src/test/resources/ctx-sanity-test.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - diff --git a/testing/sanity/src/test/resources/logback-test.xml b/testing/sanity/src/test/resources/logback-test.xml deleted file mode 100644 index 7689b2d6770..00000000000 --- a/testing/sanity/src/test/resources/logback-test.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - ./target/test.log - - - %date [%thread] %-5level [%X{subsystem}]\(%logger{46}\): %message%n - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/testing/sanity/src/test/resources/repo/connector-broken.xml b/testing/sanity/src/test/resources/repo/connector-broken.xml deleted file mode 100644 index 6c04d464565..00000000000 --- a/testing/sanity/src/test/resources/repo/connector-broken.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - ICF Broken Connector - http://midpoint.evolveum.com/xml/ns/public/connector/icf-1 - this.connector.type.does.not.Exist - 1.1.0.0-e1 - non.existent.connector.bundle - http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/non.existent.connector.bundle - - - - diff --git a/testing/sanity/src/test/resources/repo/resource-broken.xml b/testing/sanity/src/test/resources/repo/resource-broken.xml deleted file mode 100644 index 07d1b18c55f..00000000000 --- a/testing/sanity/src/test/resources/repo/resource-broken.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - Broken Resource - - - - c:connectorType - this.connector.type.does.not.Exist - - - - - - - - - - - http://midpoint.evolveum.com/xml/ns/public/resource/instance/ef2bc95b-76e0-59e2-ffff-ffffffffffff - diff --git a/testing/sanity/src/test/resources/repo/resource-derby.xml b/testing/sanity/src/test/resources/repo/resource-derby.xml deleted file mode 100644 index 5476a2baf25..00000000000 --- a/testing/sanity/src/test/resources/repo/resource-derby.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - Embedded Test Derby - - - - c:connectorType - org.identityconnectors.databasetable.DatabaseTableConnector - - - - - - - org.apache.derby.jdbc.ClientDriver - jdbc:derby://%h:%p/%d - login - password - secret - users - midpoint - target/derbyMidPointTest - localhost - 11527 - - - - http://midpoint.evolveum.com/xml/ns/public/resource/instance/ef2bc95b-76e0-59e2-86d6-999902d3abab - - - - - - - diff --git a/testing/sanity/src/test/resources/repo/resource-dummy.xml b/testing/sanity/src/test/resources/repo/resource-dummy.xml deleted file mode 100644 index e73d84d7974..00000000000 --- a/testing/sanity/src/test/resources/repo/resource-dummy.xml +++ /dev/null @@ -1,322 +0,0 @@ - - - - - - - Dummy Resource - dummy resource - - - - - - connectorType - com.evolveum.icf.dummy.connector.DummyConnector - - - connectorVersion - 2.0 - - - - - - - - - - - - - http://midpoint.evolveum.com/xml/ns/public/resource/instance/10000000-0000-0000-0000-000000000004 - - - - - - - - - - - icfs:uid - icfs:name - icfs:name - icfs:name - __ACCOUNT__ - account - - - - - - - - ICF UID - read - - - - - - - - - - ICF NAME - - - - - - - - - - - - - - - - - - - default - Default Account - true - ri:AccountObjectClass - - icfs:name - Username - - weak - - $user/name - - - - - - - - weak - - $c:user/c:name - - - - - icfs:uid - UID - - - ri:fullname - Full Name - - - $user/fullName - - - - weak - - $user/fullName - - - - - ri:location - Location - - strong - - - $c:user/c:locality - - - - - http://midpoint.evolveum.com/xml/ns/public/provisioning/channels-3#import - - - - - description - - - - - ri:ship - Ship - - - - - - organizationalUnit - - - - - ri:loot - Loot - - http://pirates.net/avast - - 10000 - - - - - ri:weapon - Weapon - - - - $user/extension/piracy:weapon - - - - - - ri:drink - Drink - false - - strong - - rum - - - - - ri:quote - Quote - true - - strong - - Arr! - - - - - - 5 - - - - - - attributes/name - daviejones - - - - - - - attributes/name - calypso - - - - - - - - - - - - - - - - - - - - - - - weak - - - - - - - - - - - - - true - - - - - true - - - c:name - - $account/attributes/icfs:name - - - - - linked - http://midpoint.evolveum.com/xml/ns/public/model/action-3#modifyUser - - - deleted - http://midpoint.evolveum.com/xml/ns/public/model/action-3#unlinkAccount - - - unlinked - http://midpoint.evolveum.com/xml/ns/public/model/action-3#linkAccount - - - unmatched - http://midpoint.evolveum.com/xml/ns/public/provisioning/channels-3#import - http://midpoint.evolveum.com/xml/ns/public/model/action-3#addUser - - - - - diff --git a/testing/sanity/src/test/resources/repo/resource-opendj-legacy.xml b/testing/sanity/src/test/resources/repo/resource-opendj-legacy.xml deleted file mode 100644 index 7b26b380936..00000000000 --- a/testing/sanity/src/test/resources/repo/resource-opendj-legacy.xml +++ /dev/null @@ -1,707 +0,0 @@ - - - - - - - - - Embedded Test OpenDJ - - - - Dummy description, just for the test - - - c:connectorType - org.identityconnectors.ldap.LdapConnector - - - - - - - - - - - 10389 - localhost - dc=example,dc=com - cn=directory manager - - secret - - uid - ds-pwp-account-disabled - - - - - - 120000 - - 1 - 10 - 10 - 150000 - - - 100 - - - -1 - -1 - -1 - -1 - -1 - - -1 - -1 - -1 - -1 - -1 - -1 - - -1 - - - - - - http://midpoint.evolveum.com/xml/ns/public/resource/instance/ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff - - - - - - - - account - default - - Default Account - - true - - - ri:AccountObjectClass - - - - icfs:name - - - Distinguished Name - - mr:stringIgnoreCase - - - - - - declare default namespace "http://midpoint.evolveum.com/xml/ns/public/common/common-3";$user/name - - - - - - - - - - - - - icfs:uid - - - Entry UUID - - - - - - mr:stringIgnoreCase - - - - - - - ri:cn - Common Name - - - - - - - declare default namespace "http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - $user/fullName - - - - - - - - - - - - declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - $i:user/i:fullName - - - - - - - - - ri:sn - - Surname - - - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";$c:user/c:familyName - - - - - - - - - - - - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";familyName - - - - - - - - ri:givenName - Given Name - - - The mapping is using relative path in default source context (which is $user) - and default expression (which is asIs). - - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";givenName - - - - - - - - - - - declare default namespace "http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - $user/givenName - - - - - - - - ri:uid - - Login Name - - mr:stringIgnoreCase - - - - It is mapped from (and also to) "name" property of user. It is essentially a login name. - This outbound construction is using a Groovy expression. - - - weak - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";$user/name - - - - - - - - It is mapped to (and also from) "name" property of user. It is essentially a login name - - weak - - - - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";$user/name - - - - - - - - ri:description - - - - weak - - Created by IDM - - - - - - - declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - declare namespace my="http://whatever.com/my"; - $i:user/i:extension/my:description - - - - - - - - - ri:carLicense - - - This attibute definition is used to test tolerance of empty values. - - - - - The expression will produce empty value. OpenDJ will die if empty value - is provided for an attribute. midPoint should filter out the empty value - and do not sent it to OpenDJ. - - weak - - - - - - - - - declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - declare namespace my="http://whatever.com/my"; - $i:user/i:extension/my:description - - - - - - - - ri:employeeType - - - This attibute definition is used to test inboud mapping when deleting the value from attribute. - - - - - - declare default namespace "http://midpoint.evolveum.com/xml/ns/public/common/common-3";$user/employeeType - - - - - - - ri:displayName - Display Name - - - It is mapped from "fullName" property of user using ECMAScript (JavaScript) expression. - - - $user/fullName - - - - - - - - - ri:postalAddress - Display Name - - - Conditional expression. It will be evaluated only if user's employee number is set. - - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";$c:user/c:employeeNumber - - - - - - - - - - - - - - ri:l - false - - - - strong - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";$c:user/c:locality - - - - - - - - - - - - - - - - - ri:group - LDAP Group Membership - entitlement - ldapGroup - objectToSubject - ri:uniqueMember - icfs:name - - - - - - - - - - - - - - - - - - - http://midpoint.evolveum.com/xml/ns/public/model/channels-3#webService - - - - - - - - weak - http://midpoint.evolveum.com/xml/ns/public/model/channels-3#webService - - - - - - - - - - - - entitlement - ldapGroup - LDAP Group - ri:GroupObjectClass - - - - - - - - - ri:ds-pwp-account-disabled - - true - - - - - - - - - - true - - - - - - - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";c:name - - - - - - - - - - - - - - - linked - true - - - deleted - true - - http://midpoint.evolveum.com/xml/ns/public/model/action-3#unlink - - - - unlinked - true - - http://midpoint.evolveum.com/xml/ns/public/model/action-3#link - - - - unmatched - true - - http://midpoint.evolveum.com/xml/ns/public/model/action-3#addFocus - - - - - - diff --git a/testing/sanity/src/test/resources/repo/resource-opendj.xml b/testing/sanity/src/test/resources/repo/resource-opendj.xml deleted file mode 100644 index 324e46ee63f..00000000000 --- a/testing/sanity/src/test/resources/repo/resource-opendj.xml +++ /dev/null @@ -1,670 +0,0 @@ - - - - - - - - - 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 - - - - - - 120000 - - 1 - 10 - 10 - 150000 - - - 100 - - - -1 - -1 - -1 - -1 - -1 - - -1 - -1 - -1 - -1 - -1 - -1 - - -1 - - - - false - false - false - - - - - - http://midpoint.evolveum.com/xml/ns/public/resource/instance/ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff - - - - - - - - account - default - - Default Account - - true - - - ri:inetOrgPerson - - - - ri:dn - - - Distinguished Name - - mr:stringIgnoreCase - - - - - - $focus/name - - - - - - - - - - - - - ri:entryUUID - - - Entry UUID - - - - - - mr:stringIgnoreCase - - - - - - - ri:cn - Common Name - - - - - - - declare default namespace "http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - $user/fullName - - - - - - - - - - - fullName - - - - - - - - ri:sn - - Surname - - - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";$c:user/c:familyName - - - - - - - - - - - - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";familyName - - - - - - - - ri:givenName - Given Name - - - The mapping is using relative path in default source context (which is $user) - and default expression (which is asIs). - - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";givenName - - - - - - - - - - - declare default namespace "http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - $user/givenName - - - - - - - - ri:uid - - Login Name - - mr:stringIgnoreCase - - - - It is mapped from (and also to) "name" property of user. It is essentially a login name. - This outbound construction is using a Groovy expression. - - - weak - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";$user/name - - - - - - - - It is mapped to (and also from) "name" property of user. It is essentially a login name - - weak - - - - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";$user/name - - - - - - - - ri:description - - - - weak - - Created by IDM - - - - - - - declare namespace i="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - declare namespace my="http://whatever.com/my"; - $i:user/i:extension/my:description - - - - - - - - - ri:carLicense - - - This attibute definition is used to test tolerance of empty values. - - - - - The expression will produce empty value. OpenDJ will die if empty value - is provided for an attribute. midPoint should filter out the empty value - and do not sent it to OpenDJ. - - weak - - - - - - - - - - - - - - - - - - - ri:employeeType - - - This attibute definition is used to test inboud mapping when deleting the value from attribute. - - - - - - declare default namespace "http://midpoint.evolveum.com/xml/ns/public/common/common-3";$user/employeeType - - - - - - - ri:displayName - Display Name - - - It is mapped from "fullName" property of user using ECMAScript (JavaScript) expression. - - - $user/fullName - - - - - - - - - ri:postalAddress - Display Name - - - Conditional expression. It will be evaluated only if user's employee number is set. - - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";$c:user/c:employeeNumber - - - - - - - - - - - - - - ri:l - false - - - - strong - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3";$c:user/c:locality - - - - - - - - - - - - - - - - - ri:group - LDAP Group Membership - entitlement - ldapGroup - objectToSubject - ri:uniqueMember - ri:dn - - - - - - - - - - - - - - - - - - - http://midpoint.evolveum.com/xml/ns/public/model/channels-3#webService - - - - - - - - weak - http://midpoint.evolveum.com/xml/ns/public/model/channels-3#webService - - - - - - - - - - - - entitlement - ldapGroup - LDAP Group - ri:groupOfUniqueNames - - - - - - - - - ri:ds-pwp-account-disabled - - true - - - - - - - - - - true - - - - - - - - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - c:name - - - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - declare namespace dj="http://midpoint.evolveum.com/xml/ns/public/resource/instance/ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff"; - $c:account/c:attributes/dj:uid - - - - - - - - - - - - - - linked - true - - - deleted - true - - http://midpoint.evolveum.com/xml/ns/public/model/action-3#unlink - - - - unlinked - true - - http://midpoint.evolveum.com/xml/ns/public/model/action-3#link - - - - unmatched - true - - http://midpoint.evolveum.com/xml/ns/public/model/action-3#addFocus - - - - - - diff --git a/testing/sanity/src/test/resources/repo/role-captain.xml b/testing/sanity/src/test/resources/repo/role-captain.xml deleted file mode 100644 index 4b8315a2df3..00000000000 --- a/testing/sanity/src/test/resources/repo/role-captain.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - Captain Role - - - - - account - - ri:employeeType - - - sailor - - - - - ri:title - - strong - - Honorable Captain - - - - - ri:carLicense - - - C4PT41N - - - - - ri:businessCategory - - - cruise - - - - - ri:departmentNumber - - - declare default namespace "http://midpoint.evolveum.com/xml/ns/public/common/common-3";$user/givenName - - - - - - - - ri:destinationIndicator - - - declare default namespace "http://midpoint.evolveum.com/xml/ns/public/common/common-3";fullName - - - - - ri:physicalDeliveryOfficeName - - - - declare default namespace "http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - declare namespace my="http://whatever.com/my"; - $c:assignment/c:extension/my:shipName - - - - - - diff --git a/testing/sanity/src/test/resources/repo/role-judge.xml b/testing/sanity/src/test/resources/repo/role-judge.xml deleted file mode 100644 index 5e0b88b5a28..00000000000 --- a/testing/sanity/src/test/resources/repo/role-judge.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - Judge - - - - - account - - - - - criminal exclusion: pirate - - - - - - - - - - - diff --git a/testing/sanity/src/test/resources/repo/role-pirate.xml b/testing/sanity/src/test/resources/repo/role-pirate.xml deleted file mode 100644 index 9aab890b426..00000000000 --- a/testing/sanity/src/test/resources/repo/role-pirate.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - Pirate Role - - - - - - - - - account - - ri:title - - strong - - Bloody Pirate - - - - - ri:businessCategory - - - loot - murder - - - - - - diff --git a/testing/sanity/src/test/resources/repo/role-sailor.xml b/testing/sanity/src/test/resources/repo/role-sailor.xml deleted file mode 100644 index e9ffc50ae6d..00000000000 --- a/testing/sanity/src/test/resources/repo/role-sailor.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - Sailor Role - - - - - account - - ri:employeeType - - - sailor - - - - - - diff --git a/testing/sanity/src/test/resources/repo/role-superuser.xml b/testing/sanity/src/test/resources/repo/role-superuser.xml deleted file mode 100644 index bbb992e8733..00000000000 --- a/testing/sanity/src/test/resources/repo/role-superuser.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - Superuser - - http://midpoint.evolveum.com/xml/ns/public/security/authorization-3#all - - diff --git a/testing/sanity/src/test/resources/repo/sample-configuration-object.xml b/testing/sanity/src/test/resources/repo/sample-configuration-object.xml deleted file mode 100644 index 5c0ea8d3217..00000000000 --- a/testing/sanity/src/test/resources/repo/sample-configuration-object.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - My Sample Config Object - - - - - http://myself.me/schemas/objects#SampleConfigType - diff --git a/testing/sanity/src/test/resources/repo/system-configuration.xml b/testing/sanity/src/test/resources/repo/system-configuration.xml deleted file mode 100644 index 2895c993ff5..00000000000 --- a/testing/sanity/src/test/resources/repo/system-configuration.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - SystemConfiguration - - - REPOSITORY - INFO - IDM_LOG - - - com.evolveum.midpoint.common - DEBUG - - - com.evolveum.midpoint.util - DEBUG - - - %date [%thread] %-5level \(%logger{46}\): %message%n - target/test.log - true - - IDM_LOG - INFO - - diff --git a/testing/sanity/src/test/resources/repo/task-derby-reconciliation.xml b/testing/sanity/src/test/resources/repo/task-derby-reconciliation.xml deleted file mode 100644 index 52783e2d61b..00000000000 --- a/testing/sanity/src/test/resources/repo/task-derby-reconciliation.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - Reconciliation: Derby - - - ri:AccountObjectClass - - - 91919191-76e0-59e2-86d6-3d4f02d3dddd - - runnable - - http://midpoint.evolveum.com/xml/ns/public/model/synchronization/task/reconciliation/handler-3 - - recurring - tight - - 5 - - - diff --git a/testing/sanity/src/test/resources/repo/task-opendj-reconciliation-legacy.xml b/testing/sanity/src/test/resources/repo/task-opendj-reconciliation-legacy.xml deleted file mode 100644 index d1483141088..00000000000 --- a/testing/sanity/src/test/resources/repo/task-opendj-reconciliation-legacy.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - Reconciliation: OpenDJ - - - ri:AccountObjectClass - - - 91919191-76e0-59e2-86d6-3d4f02d30000 - - runnable - - http://midpoint.evolveum.com/xml/ns/public/model/synchronization/task/reconciliation/handler-3 - - recurring - tight - - 5 - - - diff --git a/testing/sanity/src/test/resources/repo/task-opendj-reconciliation.xml b/testing/sanity/src/test/resources/repo/task-opendj-reconciliation.xml deleted file mode 100644 index ccd12281695..00000000000 --- a/testing/sanity/src/test/resources/repo/task-opendj-reconciliation.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - Reconciliation: OpenDJ - - - ri:inetOrgPerson - - - 91919191-76e0-59e2-86d6-3d4f02d30000 - - runnable - - http://midpoint.evolveum.com/xml/ns/public/model/synchronization/task/reconciliation/handler-3 - - recurring - tight - - 5 - - - diff --git a/testing/sanity/src/test/resources/repo/task-opendj-sync-legacy.xml b/testing/sanity/src/test/resources/repo/task-opendj-sync-legacy.xml deleted file mode 100644 index 892595d1f45..00000000000 --- a/testing/sanity/src/test/resources/repo/task-opendj-sync-legacy.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - Synchronization: Embedded Test OpenDJ - - - capsized - 42 - ri:AccountObjectClass - - - 91919191-76e0-59e2-86d6-3d4f02d3ffff - - runnable - - http://midpoint.evolveum.com/xml/ns/public/model/synchronization/task/live-sync/handler-3 - - recurring - tight - - 3 - - - diff --git a/testing/sanity/src/test/resources/repo/task-opendj-sync.xml b/testing/sanity/src/test/resources/repo/task-opendj-sync.xml deleted file mode 100644 index 6c71c019b1f..00000000000 --- a/testing/sanity/src/test/resources/repo/task-opendj-sync.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - Synchronization: Embedded Test OpenDJ - - - capsized - 42 - - - - 91919191-76e0-59e2-86d6-3d4f02d3ffff - - runnable - - http://midpoint.evolveum.com/xml/ns/public/model/synchronization/task/live-sync/handler-3 - - recurring - tight - - 3 - - - diff --git a/testing/sanity/src/test/resources/repo/task-user-recompute.xml b/testing/sanity/src/test/resources/repo/task-user-recompute.xml deleted file mode 100644 index 6a1f736cc23..00000000000 --- a/testing/sanity/src/test/resources/repo/task-user-recompute.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - User Recompute - - - - - - - runnable - - http://midpoint.evolveum.com/xml/ns/public/model/synchronization/task/recompute/handler-3 - single - tight - - diff --git a/testing/sanity/src/test/resources/repo/user-administrator.xml b/testing/sanity/src/test/resources/repo/user-administrator.xml deleted file mode 100644 index 2065d6669df..00000000000 --- a/testing/sanity/src/test/resources/repo/user-administrator.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - administrator - midPoint Administrator - midPoint - Administrator - administrator@evolveum.com - - - - - - http://www.w3.org/2001/04/xmlenc#aes128-cbc - - - 4HXeUejV93Vd3JuIZz7sbs5bVko= - - - Q27VymuHR348Vb9Ln5p06RT667FqZPSijEMxVDWw7D8= - - - - - - - - - - - - - - - - - - - - diff --git a/testing/sanity/src/test/resources/repo/user-e.xml b/testing/sanity/src/test/resources/repo/user-e.xml deleted file mode 100644 index 1648a82ee70..00000000000 --- a/testing/sanity/src/test/resources/repo/user-e.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - e - e - e - e - e - - - - deadmentellnotales - - - - diff --git a/testing/sanity/src/test/resources/repo/user-guybrush.xml b/testing/sanity/src/test/resources/repo/user-guybrush.xml deleted file mode 100644 index e4a39f54720..00000000000 --- a/testing/sanity/src/test/resources/repo/user-guybrush.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - guybrush - Guybrush Threepwood - Guybrush - Threepwood - guybrush@evolveum.com - Loosers - Deep in the Caribbean - A - B - C - - - - - - howMuchWoodWouldWoodchuckChuckIfWoodchuckCouldChuckWood - - - - diff --git a/testing/sanity/src/test/resources/repo/user-jack.xml b/testing/sanity/src/test/resources/repo/user-jack.xml deleted file mode 100644 index aba5e834fbe..00000000000 --- a/testing/sanity/src/test/resources/repo/user-jack.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - jack - - Black Pearl - - Jack Sparrow - Jack - Sparrow - Jackie - Cpt. - - PhD. - jack.sparrow@evolveum.com - 555-1234 - CAPTAIN - Leaders - Black Pearl - - - enabled - - - - - - deadmentellnotales - - - - diff --git a/testing/sanity/src/test/resources/repo/user-template.xml b/testing/sanity/src/test/resources/repo/user-template.xml deleted file mode 100644 index 61a593b8edc..00000000000 --- a/testing/sanity/src/test/resources/repo/user-template.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - Default User Template - - - - weak - - declare default namespace "http://midpoint.evolveum.com/xml/ns/public/common/common-3";$user/givenName - - - declare default namespace "http://midpoint.evolveum.com/xml/ns/public/common/common-3";$user/familyName - - - - - - declare default namespace "http://midpoint.evolveum.com/xml/ns/public/common/common-3";fullName - - - - diff --git a/testing/sanity/src/test/resources/request/account-angelika-legacy.xml b/testing/sanity/src/test/resources/request/account-angelika-legacy.xml deleted file mode 100644 index 2f66a623315..00000000000 --- a/testing/sanity/src/test/resources/request/account-angelika-legacy.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - ri:AccountObjectClass - - uid=angelika,ou=people,dc=example,dc=com - angelika - Angelika Marley - Angelika - Marley - - diff --git a/testing/sanity/src/test/resources/request/account-angelika.xml b/testing/sanity/src/test/resources/request/account-angelika.xml deleted file mode 100644 index 3a3f6ffe5b1..00000000000 --- a/testing/sanity/src/test/resources/request/account-angelika.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - ri:inetOrgPerson - - uid=angelika,ou=people,dc=example,dc=com - angelika - Angelika Marley - Angelika - Marley - - diff --git a/testing/sanity/src/test/resources/request/account-modify-attrs.xml b/testing/sanity/src/test/resources/request/account-modify-attrs.xml deleted file mode 100644 index 789c3c858b7..00000000000 --- a/testing/sanity/src/test/resources/request/account-modify-attrs.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - modify - c:ShadowType - will be replaced by the test code - - replace - - declare namespace c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"; - declare namespace ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance/ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff"; - c:attributes/ri:roomNumber - - captain's cabin - - - add - declare namespace ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance/ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff";c:attributes/ri:businessCategory - capsize - fighting - - - add - declare namespace ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance/ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff";c:attributes/ri:employeeType - A - - diff --git a/testing/sanity/src/test/resources/request/account-modify-bad-path.xml b/testing/sanity/src/test/resources/request/account-modify-bad-path.xml deleted file mode 100644 index 46cfe3ebb3a..00000000000 --- a/testing/sanity/src/test/resources/request/account-modify-bad-path.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - modify - c:ShadowType - will be replaced by the test code - - replace - attributes/thisAttributeDoesNotExist - whatever - - diff --git a/testing/sanity/src/test/resources/request/account-modify-roomnumber-explicit-type.xml b/testing/sanity/src/test/resources/request/account-modify-roomnumber-explicit-type.xml deleted file mode 100644 index ccf6ba8031d..00000000000 --- a/testing/sanity/src/test/resources/request/account-modify-roomnumber-explicit-type.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - modify - c:ShadowType - will be replaced by the test code - - replace - attributes/roomNumber - upperdeck - - diff --git a/testing/sanity/src/test/resources/request/account-modify-roomnumber.xml b/testing/sanity/src/test/resources/request/account-modify-roomnumber.xml deleted file mode 100644 index 3d90e2826de..00000000000 --- a/testing/sanity/src/test/resources/request/account-modify-roomnumber.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - modify - c:ShadowType - will be replaced by the test code - - replace - attributes/roomNumber - quarterdeck - - diff --git a/testing/sanity/src/test/resources/request/angelika.ldif b/testing/sanity/src/test/resources/request/angelika.ldif deleted file mode 100644 index da3a3f2cf80..00000000000 --- a/testing/sanity/src/test/resources/request/angelika.ldif +++ /dev/null @@ -1,16 +0,0 @@ -dn: uid=angelika,ou=People,dc=example,dc=com -uid: angelika -cn: Angelika Marley -sn: Marley -givenname: Angelika -objectclass: top -objectclass: person -objectclass: organizationalPerson -objectclass: inetOrgPerson -l: Caribbean -employeeType: governor -title: Governor -businessCategory: state -mail: governor.marley@deep.in.the.caribbean.com -userpassword: piranhaDogs - diff --git a/testing/sanity/src/test/resources/request/e-create.ldif b/testing/sanity/src/test/resources/request/e-create.ldif deleted file mode 100644 index 8bb545eb729..00000000000 --- a/testing/sanity/src/test/resources/request/e-create.ldif +++ /dev/null @@ -1,15 +0,0 @@ -dn: uid=e,ou=People,dc=example,dc=com -uid: e -cn: e -sn: e -givenname: e -objectclass: top -objectclass: person -objectclass: organizationalPerson -objectclass: inetOrgPerson -l: middle of nowhere -mail: e@example.com -telephonenumber: +1 408 555 1234 -facsimiletelephonenumber: +1 408 555 4321 -userpassword: supersecret - diff --git a/testing/sanity/src/test/resources/request/elaine.ldif b/testing/sanity/src/test/resources/request/elaine.ldif deleted file mode 100644 index 4c1efe5862c..00000000000 --- a/testing/sanity/src/test/resources/request/elaine.ldif +++ /dev/null @@ -1,16 +0,0 @@ -dn: uid=elaine,ou=People,dc=example,dc=com -uid: elaine -cn: Elaine Marley -sn: Marley -givenname: Elaine -objectclass: top -objectclass: person -objectclass: organizationalPerson -objectclass: inetOrgPerson -l: Caribbean -employeeType: governor -title: Governor -businessCategory: state -mail: governor.marley@deep.in.the.caribbean.com -userpassword: piranhaDogs - diff --git a/testing/sanity/src/test/resources/request/gibbs-modify.ldif b/testing/sanity/src/test/resources/request/gibbs-modify.ldif deleted file mode 100644 index 15f2135fb96..00000000000 --- a/testing/sanity/src/test/resources/request/gibbs-modify.ldif +++ /dev/null @@ -1,5 +0,0 @@ -dn: uid=jgibbs,ou=People,dc=example,dc=com -changetype: modify -replace: l -l: middle of nowhere -- diff --git a/testing/sanity/src/test/resources/request/herman.ldif b/testing/sanity/src/test/resources/request/herman.ldif deleted file mode 100644 index ec84efdf96a..00000000000 --- a/testing/sanity/src/test/resources/request/herman.ldif +++ /dev/null @@ -1,18 +0,0 @@ -dn: uid=herman,ou=People,dc=example,dc=com -uid: herman -cn: Herman Toothrot -cn: Horatio Torquemeda Marley -sn: Marley -sn: Toothrot -givenname: Herman -givenname: Horatio -objectclass: top -objectclass: person -objectclass: organizationalPerson -objectclass: inetOrgPerson -l: Monkey Island -employeeType: governor -employeeType: hermit -mail: ht@monkeyisland.com -userpassword: creepyOldHermit - diff --git a/testing/sanity/src/test/resources/request/user-modify-activation-disable.xml b/testing/sanity/src/test/resources/request/user-modify-activation-disable.xml deleted file mode 100644 index 3a55053ed4a..00000000000 --- a/testing/sanity/src/test/resources/request/user-modify-activation-disable.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - modify - c:UserType - c0c010c0-d34d-b33f-f00d-111111111111 - - - replace - c:activation/c:administrativeStatus - disabled - - diff --git a/testing/sanity/src/test/resources/request/user-modify-activation-enable.xml b/testing/sanity/src/test/resources/request/user-modify-activation-enable.xml deleted file mode 100644 index 897ec92722c..00000000000 --- a/testing/sanity/src/test/resources/request/user-modify-activation-enable.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - modify - c:UserType - c0c010c0-d34d-b33f-f00d-111111111111 - - - replace - c:activation/c:administrativeStatus - enabled - - diff --git a/testing/sanity/src/test/resources/request/user-modify-add-account-derby.xml b/testing/sanity/src/test/resources/request/user-modify-add-account-derby.xml deleted file mode 100644 index 6d416dd542d..00000000000 --- a/testing/sanity/src/test/resources/request/user-modify-add-account-derby.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - modify - c:UserType - c0c010c0-d34d-b33f-f00d-111111111111 - - add - c:linkRef - - - - - - - ri:AccountObjectClass - - jsparrow - Cpt. Jack Sparrow - - - - - diff --git a/testing/sanity/src/test/resources/request/user-modify-add-account-legacy.xml b/testing/sanity/src/test/resources/request/user-modify-add-account-legacy.xml deleted file mode 100644 index 73ae3559957..00000000000 --- a/testing/sanity/src/test/resources/request/user-modify-add-account-legacy.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - modify - c:UserType - c0c010c0-d34d-b33f-f00d-111111111111 - - add - c:linkRef - - - - - - - ri:AccountObjectClass - - uid=jack,ou=People,dc=example,dc=com - jack - Jack Sparrow - Jack - Sparrow - - - - - diff --git a/testing/sanity/src/test/resources/request/user-modify-add-account.xml b/testing/sanity/src/test/resources/request/user-modify-add-account.xml deleted file mode 100644 index 34e2d17c195..00000000000 --- a/testing/sanity/src/test/resources/request/user-modify-add-account.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - modify - c:UserType - c0c010c0-d34d-b33f-f00d-111111111111 - - add - c:linkRef - - - - - - - ri:inetOrgPerson - - uid=jack,ou=People,dc=example,dc=com - jack - Jack Sparrow - Jack - Sparrow - - - - - diff --git a/testing/sanity/src/test/resources/request/user-modify-add-role-captain-1.xml b/testing/sanity/src/test/resources/request/user-modify-add-role-captain-1.xml deleted file mode 100644 index 0726abb7d01..00000000000 --- a/testing/sanity/src/test/resources/request/user-modify-add-role-captain-1.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - modify - c:UserType - c0c010c0-d34d-b33f-f00d-111111111222 - - add - c:assignment - - - The Sea Monkey - - - - - diff --git a/testing/sanity/src/test/resources/request/user-modify-add-role-captain-2.xml b/testing/sanity/src/test/resources/request/user-modify-add-role-captain-2.xml deleted file mode 100644 index 3021ebc8473..00000000000 --- a/testing/sanity/src/test/resources/request/user-modify-add-role-captain-2.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - modify - c:UserType - c0c010c0-d34d-b33f-f00d-111111111222 - - add - c:assignment - - - The Dainty Lady - - - - - diff --git a/testing/sanity/src/test/resources/request/user-modify-add-role-judge.xml b/testing/sanity/src/test/resources/request/user-modify-add-role-judge.xml deleted file mode 100644 index 635b1c389f9..00000000000 --- a/testing/sanity/src/test/resources/request/user-modify-add-role-judge.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - modify - c:UserType - c0c010c0-d34d-b33f-f00d-111111111222 - - add - c:assignment - - - - - diff --git a/testing/sanity/src/test/resources/request/user-modify-add-role-pirate.xml b/testing/sanity/src/test/resources/request/user-modify-add-role-pirate.xml deleted file mode 100644 index a1f8a7965ff..00000000000 --- a/testing/sanity/src/test/resources/request/user-modify-add-role-pirate.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - modify - c:UserType - c0c010c0-d34d-b33f-f00d-111111111222 - - add - c:assignment - - - - - diff --git a/testing/sanity/src/test/resources/request/user-modify-delete-role-captain-1.xml b/testing/sanity/src/test/resources/request/user-modify-delete-role-captain-1.xml deleted file mode 100644 index d48ab446a62..00000000000 --- a/testing/sanity/src/test/resources/request/user-modify-delete-role-captain-1.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - modify - c:UserType - c0c010c0-d34d-b33f-f00d-111111111222 - - delete - c:assignment - - - The Sea Monkey - - - - - diff --git a/testing/sanity/src/test/resources/request/user-modify-delete-role-captain-2.xml b/testing/sanity/src/test/resources/request/user-modify-delete-role-captain-2.xml deleted file mode 100644 index 939dee6cb66..00000000000 --- a/testing/sanity/src/test/resources/request/user-modify-delete-role-captain-2.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - modify - c:UserType - c0c010c0-d34d-b33f-f00d-111111111222 - - delete - c:assignment - - - The Dainty Lady - - - - - diff --git a/testing/sanity/src/test/resources/request/user-modify-delete-role-pirate.xml b/testing/sanity/src/test/resources/request/user-modify-delete-role-pirate.xml deleted file mode 100644 index d2fe6462577..00000000000 --- a/testing/sanity/src/test/resources/request/user-modify-delete-role-pirate.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - modify - c:UserType - c0c010c0-d34d-b33f-f00d-111111111222 - - delete - c:assignment - - - - - diff --git a/testing/sanity/src/test/resources/request/user-modify-fullname-locality.xml b/testing/sanity/src/test/resources/request/user-modify-fullname-locality.xml deleted file mode 100644 index 216c2864c14..00000000000 --- a/testing/sanity/src/test/resources/request/user-modify-fullname-locality.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - modify - c:UserType - c0c010c0-d34d-b33f-f00d-111111111111 - - - replace - c:fullName - Cpt. Jack Sparrow - - - - replace - c:locality - somewhere - - - - replace - c:employeeNumber - 1 - - diff --git a/testing/sanity/src/test/resources/request/user-modify-givenname.xml b/testing/sanity/src/test/resources/request/user-modify-givenname.xml deleted file mode 100644 index 1ff95edb04f..00000000000 --- a/testing/sanity/src/test/resources/request/user-modify-givenname.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - modify - c:UserType - c0c010c0-d34d-b33f-f00d-111111111111 - - replace - c:givenName - - diff --git a/testing/sanity/src/test/resources/request/user-modify-name.xml b/testing/sanity/src/test/resources/request/user-modify-name.xml deleted file mode 100644 index 3d2d2880c87..00000000000 --- a/testing/sanity/src/test/resources/request/user-modify-name.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - modify - c:UserType - c0c010c0-d34d-b33f-f00d-111111111111 - - replace - c:name - jsparrow - - diff --git a/testing/sanity/src/test/resources/request/user-modify-password.xml b/testing/sanity/src/test/resources/request/user-modify-password.xml deleted file mode 100644 index 90ca9c85495..00000000000 --- a/testing/sanity/src/test/resources/request/user-modify-password.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - modify - c:UserType - c0c010c0-d34d-b33f-f00d-111111111111 - - - replace - c:credentials/c:password/c:value - - butUnd3dM4yT4lkAL0t - - - diff --git a/testing/sanity/src/test/resources/request/will-modify.ldif b/testing/sanity/src/test/resources/request/will-modify.ldif deleted file mode 100644 index c916d6140ef..00000000000 --- a/testing/sanity/src/test/resources/request/will-modify.ldif +++ /dev/null @@ -1,5 +0,0 @@ -dn: uid=wturner,ou=People,dc=example,dc=com -changetype: modify -replace: givenName -givenName: asdf -- \ No newline at end of file diff --git a/testing/sanity/src/test/resources/request/will-without-location.ldif b/testing/sanity/src/test/resources/request/will-without-location.ldif deleted file mode 100644 index 10d750e265c..00000000000 --- a/testing/sanity/src/test/resources/request/will-without-location.ldif +++ /dev/null @@ -1,14 +0,0 @@ -dn: uid=wturner1,ou=People,dc=example,dc=com -uid: wturner1 -cn: Will Turner -sn: Turner -givenname: Will -objectclass: top -objectclass: person -objectclass: organizationalPerson -objectclass: inetOrgPerson -mail: will.turner@blackpearl.com -telephonenumber: +1 408 555 1234 -facsimiletelephonenumber: +1 408 555 4321 -userpassword: supersecret - diff --git a/testing/sanity/src/test/resources/request/will.ldif b/testing/sanity/src/test/resources/request/will.ldif deleted file mode 100644 index db793aa73f6..00000000000 --- a/testing/sanity/src/test/resources/request/will.ldif +++ /dev/null @@ -1,15 +0,0 @@ -dn: uid=wturner,ou=People,dc=example,dc=com -uid: wturner -cn: Will Turner -sn: Turner -givenname: Will -objectclass: top -objectclass: person -objectclass: organizationalPerson -objectclass: inetOrgPerson -l: Caribbean -mail: will.turner@blackpearl.com -telephonenumber: +1 408 555 1234 -facsimiletelephonenumber: +1 408 555 4321 -userpassword: supersecret - diff --git a/testing/sanity/src/test/resources/schema/extension-piracy.xsd b/testing/sanity/src/test/resources/schema/extension-piracy.xsd deleted file mode 100644 index 51217c95420..00000000000 --- a/testing/sanity/src/test/resources/schema/extension-piracy.xsd +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - 1 - - - - - diff --git a/testing/sanity/src/test/resources/schema/extension-whatever.xsd b/testing/sanity/src/test/resources/schema/extension-whatever.xsd deleted file mode 100644 index 8d0c476e098..00000000000 --- a/testing/sanity/src/test/resources/schema/extension-whatever.xsd +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - diff --git a/testing/sanity/testng-integration.xml b/testing/sanity/testng-integration.xml deleted file mode 100644 index a0a33f51764..00000000000 --- a/testing/sanity/testng-integration.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - diff --git a/testing/story/pom.xml b/testing/story/pom.xml index ece0c3b981f..87d271188f7 100644 --- a/testing/story/pom.xml +++ b/testing/story/pom.xml @@ -169,10 +169,6 @@ org.apache.commons commons-lang3 - - commons-lang - commons-lang - commons-io commons-io diff --git a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestConsistencyMechanism.java b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestConsistencyMechanism.java index 63c5e7083ff..3585521f5da 100644 --- a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestConsistencyMechanism.java +++ b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestConsistencyMechanism.java @@ -10,7 +10,6 @@ import static com.evolveum.midpoint.prism.util.PrismTestUtil.getPrismContext; import static com.evolveum.midpoint.test.IntegrationTestTools.assertNoRepoThreadLocalCache; -import static com.evolveum.midpoint.test.IntegrationTestTools.displayJaxb; import java.io.File; import java.io.IOException; @@ -23,7 +22,7 @@ import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.opends.server.types.Entry; import org.opends.server.util.EmbeddedUtils; import org.springframework.test.annotation.DirtiesContext; @@ -261,8 +260,6 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti repoAddObjectFromFile(USER_TEMPLATE_FILENAME, initResult); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.POSITIVE); - -// DebugUtil.setDetailedDebugDump(true); } /** @@ -288,7 +285,6 @@ public void stopResources() { */ @Test public void test000Integrity() throws Exception { - assertNotNull(modelWeb); assertNotNull(modelService); assertNotNull(repositoryService); assertNotNull(taskManager); @@ -326,22 +322,15 @@ public void test000Integrity() throws Exception { */ @Test public void test001TestConnectionOpenDJ() throws Exception { - Task task = taskManager.createTaskInstance(); - // GIVEN - + given(); assertNoRepoThreadLocalCache(); - // WHEN - OperationResultType result = modelWeb.testResource(RESOURCE_OPENDJ_OID); - - // THEN + when(); + OperationResult result = modelService.testResource(RESOURCE_OPENDJ_OID, getTestTask()); + then(); assertNoRepoThreadLocalCache(); - - displayJaxb("testResource result:", result, SchemaConstants.C_RESULT); - TestUtil.assertSuccess("testResource has failed", result); - OperationResult opResult = createOperationResult(); PrismObject resourceOpenDjRepo = repositoryService.getObject(ResourceType.class, @@ -357,11 +346,11 @@ public void test001TestConnectionOpenDJ() throws Exception { assertNotNull("Resource schema was not generated", resourceOpenDjXsdSchemaElement); PrismObject openDjResourceProvisioninig = provisioningService.getObject( - ResourceType.class, RESOURCE_OPENDJ_OID, null, task, opResult); + ResourceType.class, RESOURCE_OPENDJ_OID, null, getTestTask(), opResult); display("Initialized OpenDJ resource resource (provisioning)", openDjResourceProvisioninig); PrismObject openDjResourceModel = provisioningService.getObject(ResourceType.class, - RESOURCE_OPENDJ_OID, null, task, opResult); + RESOURCE_OPENDJ_OID, null, getTestTask(), opResult); display("Initialized OpenDJ resource OpenDJ resource (model)", openDjResourceModel); checkOpenDjResource(resourceTypeOpenDjrepo, "repository"); @@ -373,8 +362,6 @@ public void test001TestConnectionOpenDJ() throws Exception { checkOpenDjResource(openDjResourceProvisioninig.asObjectable(), "provisioning"); checkOpenDjResource(openDjResourceModel.asObjectable(), "model"); - // TODO: model web - } /** diff --git a/tools/ninja/pom.xml b/tools/ninja/pom.xml index f556943bce9..5646778504e 100644 --- a/tools/ninja/pom.xml +++ b/tools/ninja/pom.xml @@ -152,10 +152,6 @@ runtime - - commons-lang - commons-lang - org.apache.commons commons-lang3 diff --git a/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/action/SchemaRepositoryAction.java b/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/action/SchemaRepositoryAction.java index c0763c5081f..e762ce5ab47 100644 --- a/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/action/SchemaRepositoryAction.java +++ b/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/action/SchemaRepositoryAction.java @@ -6,8 +6,9 @@ */ package com.evolveum.midpoint.ninja.action; +import org.apache.commons.lang3.NotImplementedException; + import com.evolveum.midpoint.ninja.opts.SchemaOptions; -import org.apache.commons.lang.NotImplementedException; /** * Created by Viliam Repan (lazyman). diff --git a/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/action/TransformRepositoryAction.java b/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/action/TransformRepositoryAction.java index ead0308bf7f..efa6c61af7a 100644 --- a/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/action/TransformRepositoryAction.java +++ b/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/action/TransformRepositoryAction.java @@ -6,8 +6,9 @@ */ package com.evolveum.midpoint.ninja.action; +import org.apache.commons.lang3.NotImplementedException; + import com.evolveum.midpoint.ninja.opts.TransformOptions; -import org.apache.commons.lang.NotImplementedException; /** * Created by Viliam Repan (lazyman). diff --git a/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/action/worker/ImportProducerWorker.java b/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/action/worker/ImportProducerWorker.java index 1d3017e1760..64548b19e99 100644 --- a/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/action/worker/ImportProducerWorker.java +++ b/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/action/worker/ImportProducerWorker.java @@ -24,7 +24,7 @@ import com.evolveum.midpoint.schema.constants.ObjectTypes; import com.evolveum.midpoint.schema.result.OperationResult; import org.apache.commons.io.input.ReaderInputStream; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.context.ApplicationContext; import org.w3c.dom.Element; import org.w3c.dom.Node; diff --git a/tools/schema-dist-maven-plugin/pom.xml b/tools/schema-dist-maven-plugin/pom.xml index 9d5280c1953..5b2d289c057 100644 --- a/tools/schema-dist-maven-plugin/pom.xml +++ b/tools/schema-dist-maven-plugin/pom.xml @@ -60,8 +60,8 @@ xml-resolver - commons-lang - commons-lang + org.apache.commons + commons-lang3 com.evolveum.midpoint.infra diff --git a/tools/schema-dist-maven-plugin/src/main/java/com/evolveum/midpoint/tools/schemadist/SchemaDistMojo.java b/tools/schema-dist-maven-plugin/src/main/java/com/evolveum/midpoint/tools/schemadist/SchemaDistMojo.java index 4183ebf22e2..4812f9442f1 100644 --- a/tools/schema-dist-maven-plugin/src/main/java/com/evolveum/midpoint/tools/schemadist/SchemaDistMojo.java +++ b/tools/schema-dist-maven-plugin/src/main/java/com/evolveum/midpoint/tools/schemadist/SchemaDistMojo.java @@ -25,7 +25,7 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.factory.ArtifactFactory; import org.apache.maven.artifact.resolver.ArtifactResolutionRequest; diff --git a/tools/xjc-plugin/pom.xml b/tools/xjc-plugin/pom.xml index 93c30c447b1..99d468f0399 100644 --- a/tools/xjc-plugin/pom.xml +++ b/tools/xjc-plugin/pom.xml @@ -48,8 +48,8 @@ codemodel - commons-lang - commons-lang + org.apache.commons + commons-lang3 org.jvnet.jaxb2_commons diff --git a/tools/xjc-plugin/src/main/java/com/evolveum/midpoint/schema/xjc/PrefixMapper.java b/tools/xjc-plugin/src/main/java/com/evolveum/midpoint/schema/xjc/PrefixMapper.java index ba9986a2029..4bf47eec321 100644 --- a/tools/xjc-plugin/src/main/java/com/evolveum/midpoint/schema/xjc/PrefixMapper.java +++ b/tools/xjc-plugin/src/main/java/com/evolveum/midpoint/schema/xjc/PrefixMapper.java @@ -28,6 +28,8 @@ public enum PrefixMapper { S("http://midpoint.evolveum.com/xml/ns/public/model/situation-1.xsd", "SITUATION"), + SC("http://midpoint.evolveum.com/xml/ns/public/model/scripting-3", "SCRIPTING"), + ICF_S("http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3", "ICF_SCHEMA"), ICF_C("http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3", "ICF_CONFIGURATION"), diff --git a/tools/xjc-plugin/src/main/java/com/evolveum/midpoint/schema/xjc/schema/FieldBox.java b/tools/xjc-plugin/src/main/java/com/evolveum/midpoint/schema/xjc/schema/FieldBox.java index 3303adce8aa..0e1b7241d57 100644 --- a/tools/xjc-plugin/src/main/java/com/evolveum/midpoint/schema/xjc/schema/FieldBox.java +++ b/tools/xjc-plugin/src/main/java/com/evolveum/midpoint/schema/xjc/schema/FieldBox.java @@ -7,7 +7,7 @@ package com.evolveum.midpoint.schema.xjc.schema; -import org.apache.commons.lang.Validate; +import org.apache.commons.lang3.Validate; /** * @author lazyman @@ -19,7 +19,7 @@ public class FieldBox implements Comparable { public FieldBox(String fieldName, T value) { Validate.notEmpty(fieldName, "Field name must not be null or empty."); - Validate.notNull("QName must not be null."); + Validate.notNull(value); this.fieldName = fieldName; this.value = value; 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 9c13d0e740a..a28d9153517 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 @@ -30,7 +30,7 @@ import com.sun.tools.xjc.reader.xmlschema.bindinfo.BIDeclaration; import com.sun.tools.xjc.reader.xmlschema.bindinfo.BIXPluginCustomization; import com.sun.xml.xsom.*; -import org.apache.commons.lang.Validate; +import org.apache.commons.lang3.Validate; import org.jetbrains.annotations.NotNull; import org.jvnet.jaxb2_commons.lang.Equals; import org.jvnet.jaxb2_commons.lang.HashCode; @@ -109,6 +109,7 @@ public class SchemaProcessor implements Processor { private static final String METHOD_PRISM_UTIL_SET_REFERENCE_VALUE_AS_REF = "setReferenceValueAsRef"; private static final String METHOD_PRISM_UTIL_SET_REFERENCE_VALUE_AS_OBJECT = "setReferenceValueAsObject"; private static final String METHOD_PRISM_UTIL_GET_REFERENCE_FILTER_CLAUSE_XNODE = "getReferenceFilterClauseXNode"; + private static final String METHOD_PRISM_UTIL_GET_FILTER = "getFilter"; private static final String METHOD_PRISM_UTIL_SET_REFERENCE_FILTER_CLAUSE_XNODE = "setReferenceFilterClauseXNode"; private static final String METHOD_PRISM_UTIL_GET_REFERENCE_TARGET_NAME = "getReferenceTargetName"; private static final String METHOD_PRISM_UTIL_SET_REFERENCE_TARGET_NAME = "setReferenceTargetName"; @@ -335,13 +336,9 @@ private void updateObjectReferenceFilter(JDefinedClass definedClass, JMethod asR copyAnnotations(getFilter, filterField); definedClass.removeField(filterField); JBlock body = getFilter.body(); - JType innerFilterType = getFilter.type(); - JVar filterClassVar = body.decl(innerFilterType, "filter", JExpr._new(innerFilterType)); - JInvocation getFilterElementInvocation =CLASS_MAP.get(PrismForJAXBUtil.class).staticInvoke(METHOD_PRISM_UTIL_GET_REFERENCE_FILTER_CLAUSE_XNODE); + JInvocation getFilterElementInvocation = CLASS_MAP.get(PrismForJAXBUtil.class).staticInvoke(METHOD_PRISM_UTIL_GET_FILTER); getFilterElementInvocation.arg(JExpr.invoke(asReferenceValue)); - JInvocation setFilterInvocation = body.invoke(filterClassVar, "setFilterClauseXNode"); - setFilterInvocation.arg(getFilterElementInvocation); - body._return(filterClassVar); + body._return(getFilterElementInvocation); JMethod setFilter = recreateMethod(findMethod(definedClass, "setFilter"), definedClass); body = setFilter.body();