Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/support-4.8' into s…
Browse files Browse the repository at this point in the history
…upport-4.8
  • Loading branch information
skublik committed Apr 29, 2024
2 parents e83b3b2 + b5a617e commit 189d8f6
Show file tree
Hide file tree
Showing 26 changed files with 1,067 additions and 168 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.xml.datatype.Duration;

import com.evolveum.midpoint.repo.common.subscription.SubscriptionStateCache;

import jakarta.servlet.ServletContext;
import org.apache.commons.configuration2.Configuration;
import org.apache.commons.io.FileUtils;
import org.apache.wicket.*;
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
Expand All @@ -43,6 +45,8 @@
import org.apache.wicket.markup.html.SecurePackageResourceGuard;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.pageStore.IPageStore;
import org.apache.wicket.pageStore.disk.NestedFolders;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.request.mapper.parameter.PageParametersEncoder;
import org.apache.wicket.request.resource.PackageResourceReference;
Expand Down Expand Up @@ -94,6 +98,7 @@
import com.evolveum.midpoint.repo.common.SystemObjectCache;
import com.evolveum.midpoint.repo.common.expression.ExpressionFactory;
import com.evolveum.midpoint.repo.common.subscription.SubscriptionState;
import com.evolveum.midpoint.repo.common.subscription.SubscriptionStateCache;
import com.evolveum.midpoint.schema.RelationRegistry;
import com.evolveum.midpoint.schema.SchemaService;
import com.evolveum.midpoint.schema.result.OperationResult;
Expand Down Expand Up @@ -168,6 +173,10 @@ public class MidPointApplication extends AuthenticatedWebApplication implements
@Autowired @Qualifier("descriptorLoader") private DescriptorLoader descriptorLoader;
@Value("${midpoint.additionalPackagesToScan:}") private String additionalPackagesToScan;
@Value("${wicket.request-cycle.timeout:60s}") private java.time.Duration requestCycleTimeout;
/**
* If set to false, we will not clean up disk page store files during application initialization.
*/
@Value("${wicket.disk-page-store.cleanupOnStart:true}") private boolean diskPageStoreCleanupOnStart;

private WebApplicationConfiguration webApplicationConfiguration;

Expand Down Expand Up @@ -323,6 +332,43 @@ public void updateAjaxAttributes(AbstractDefaultAjaxBehavior behavior, AjaxReque
settings.setIncludeJavascriptFull(false);
settings.setIncludeJavascript(false);
settings.setIncludeCss(false);

cleanupWicketFileStore();
}

/**
* Currently default wicket {@link org.apache.wicket.pageStore.DiskPageStore} doesn't clear unused/old files created
* from sessions created in previous server runs.
*
* Also, if page store index wasn't created during previous shutdown, all existing files in this page store will never
* be removed.
*
* See MID-9430
*/
private void cleanupWicketFileStore() {
if (!diskPageStoreCleanupOnStart) {
return;
}

setPageManagerProvider(new DefaultPageManagerProvider(this) {

@Override
protected IPageStore newPersistentStore() {
File fileStoreFolder = application.getStoreSettings().getFileStoreFolder();

NestedFolders folders = new NestedFolders(new File(fileStoreFolder, application.getName() + "-filestore"));
File wicketStoreBase = folders.getBase();
if (wicketStoreBase.exists() && wicketStoreBase.isDirectory()) {
try {
FileUtils.cleanDirectory(folders.getBase());
} catch (IOException ex) {
LOGGER.warn("Couldn't cleanup wicket store directory {}", wicketStoreBase, ex);
}
}

return super.newPersistentStore();
}
});
}

public DeploymentInformationType getDeploymentInfo() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public class ExpressionConstants {
public static final String VAR_ADMINISTRATIVE_STATUS = "administrativeStatus";
public static final ItemName VAR_ADMINISTRATIVE_STATUS_QNAME = new ItemName(SchemaConstants.NS_C, VAR_ADMINISTRATIVE_STATUS);

public static final String VAR_ASSOCIATION_TARGET_OBJECT_CLASS_DEFINITION = "associationTargetObjectClassDefinition";
public static final String VAR_ASSOCIATION_DEFINITION = "associationDefinition";

/**
* Numeric value describing the current iteration. It starts with 0 and increments on every iteration.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.Objects;
import javax.xml.namespace.QName;

import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.schema.TaskExecutionMode;
import com.evolveum.midpoint.schema.util.SimulationUtil;
import com.evolveum.midpoint.util.DebugDumpable;
Expand All @@ -23,10 +24,6 @@
import org.apache.commons.lang3.BooleanUtils;
import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.prism.AbstractFreezable;
import com.evolveum.midpoint.prism.Freezable;
import com.evolveum.midpoint.prism.Visitable;
import com.evolveum.midpoint.prism.Visitor;
import com.evolveum.midpoint.prism.path.ItemName;
import com.evolveum.midpoint.prism.util.ItemPathTypeUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
Expand Down Expand Up @@ -54,6 +51,15 @@ public ResourceObjectTypeDefinition getAssociationTarget() {
return associationTarget;
}

public String getResourceOid() {
return associationTarget.getResourceOid();
}

public QName getObjectClassName() {
// All association target types must share the same object class name, so it's OK to select any of them.
return associationTarget.getObjectClassName();
}

void setAssociationTarget(ResourceObjectTypeDefinition associationTarget) {
checkMutable();
this.associationTarget = associationTarget;
Expand All @@ -78,6 +84,10 @@ void setAssociationTarget(ResourceObjectTypeDefinition associationTarget) {
return definitionBean.getIntent();
}

public boolean hasMultipleIntents() {
return getIntents().size() > 1;
}

/** We rely on the assumptions about multiple intents described for {@link ResourceObjectAssociationType#getIntent()}. */
public @NotNull String getAnyIntent() throws ConfigurationException {
Collection<String> intents = getIntents();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ private void executeSearch(
// TODO: perhaps we should limit query to some reasonably high number of results?
SearchResultList<PrismObject<O>> objects = objectResolver.searchObjects(targetTypeClass, query, options, task, result);
for (PrismObject<O> object : objects) {
if (!isAcceptable(object)) {
if (!isAcceptable(object, context)) {
LOGGER.trace("Object {} was rejected by additional filtering", object);
continue;
}
Expand All @@ -491,7 +491,8 @@ private void executeSearch(
}

/** Provides additional filtering e.g. rejecting dead shadows as association targets. */
protected boolean isAcceptable(@NotNull PrismObject<O> object) {
protected boolean isAcceptable(@NotNull PrismObject<O> object, ExpressionEvaluationContext context)
throws ExpressionEvaluationException {
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,7 @@
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.constants.ExpressionConstants;
import com.evolveum.midpoint.schema.expression.TypedValue;
import com.evolveum.midpoint.schema.processor.ObjectFactory;
import com.evolveum.midpoint.schema.processor.ResourceAttribute;
import com.evolveum.midpoint.schema.processor.ResourceAttributeContainer;
import com.evolveum.midpoint.schema.processor.ResourceObjectDefinition;
import com.evolveum.midpoint.schema.processor.*;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.FocusTypeUtil;
import com.evolveum.midpoint.schema.util.ShadowUtil;
Expand All @@ -52,6 +49,7 @@
import org.apache.commons.collections4.CollectionUtils;
import org.jetbrains.annotations.NotNull;

import static com.evolveum.midpoint.model.common.expression.evaluator.AssociationRelatedEvaluatorUtil.getAssociationDefinition;
import static com.evolveum.midpoint.schema.GetOperationOptions.createNoFetchReadOnlyCollection;

/**
Expand Down Expand Up @@ -97,13 +95,7 @@ public PrismValueDeltaSetTriple<PrismContainerValue<ShadowAssociationType>> eval
AbstractRoleType thisRole = getRelevantRole(context);
LOGGER.trace("Evaluating association from link {} on: {}", expressionEvaluatorBean.getDescription(), thisRole);

//noinspection unchecked
var rAssocTargetDefTypedValue = (TypedValue<ResourceObjectDefinition>)
context.getVariables().get(ExpressionConstants.VAR_ASSOCIATION_TARGET_OBJECT_CLASS_DEFINITION);
if (rAssocTargetDefTypedValue == null || rAssocTargetDefTypedValue.getValue() == null) {
throw new ExpressionEvaluationException("No association target object definition variable in "+desc+"; the expression may be used in a wrong place. It is only supposed to create an association.");
}
ResourceObjectDefinition associationTargetDef = (ResourceObjectDefinition) rAssocTargetDefTypedValue.getValue();
var associationDefinition = getAssociationDefinition(context);

ShadowDiscriminatorType projectionDiscriminator = expressionEvaluatorBean.getProjectionDiscriminator();
if (projectionDiscriminator == null) {
Expand All @@ -118,7 +110,7 @@ public PrismValueDeltaSetTriple<PrismContainerValue<ShadowAssociationType>> eval
PrismContainer<ShadowAssociationType> output = outputDefinition.instantiate();

QName assocName = context.getMappingQName();
String resourceOid = associationTargetDef.getResourceOid();
String resourceOid = associationDefinition.getResourceOid();
List<String> candidateShadowOidList = new ArrayList<>();
// Always process the first role (myself) regardless of recursion setting
gatherCandidateShadowsFromAbstractRole(thisRole, candidateShadowOidList);
Expand Down Expand Up @@ -208,10 +200,12 @@ private void selectMatchingShadows(List<String> candidateShadowsOidList,
List<PrismObject<ShadowType>> objects = objectResolver
.searchObjects(ShadowType.class, query, createNoFetchReadOnlyCollection(), context.getTask(), result);
for (PrismObject<ShadowType> object : objects) {
PrismContainerValue<ShadowAssociationType> newValue = output.createNewValue();
ShadowAssociationType shadowAssociationType = newValue.asContainerable();
shadowAssociationType.setName(assocName);
toAssociation(object, shadowAssociationType);
if (ShadowUtil.isNotDead(object)) {
PrismContainerValue<ShadowAssociationType> newValue = output.createNewValue();
ShadowAssociationType shadowAssociationType = newValue.asContainerable();
shadowAssociationType.setName(assocName);
toAssociation(object, shadowAssociationType);
}
}
} catch (CommonException e) {
throw new SystemException("Couldn't search for relevant shadows: " + e.getMessage(), e);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2010-2024 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.expression.evaluator;

import com.evolveum.midpoint.repo.common.expression.ExpressionEvaluationContext;
import com.evolveum.midpoint.schema.constants.ExpressionConstants;
import com.evolveum.midpoint.schema.processor.ResourceAssociationDefinition;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;

import org.jetbrains.annotations.NotNull;

class AssociationRelatedEvaluatorUtil {

static @NotNull ResourceAssociationDefinition getAssociationDefinition(ExpressionEvaluationContext context)
throws ExpressionEvaluationException {
var associationDefinitionTypedValue = context.getVariables().get(ExpressionConstants.VAR_ASSOCIATION_DEFINITION);
var associationDefinition = associationDefinitionTypedValue != null ?
(ResourceAssociationDefinition) associationDefinitionTypedValue.getValue() : null;
if (associationDefinition == null) {
throw new ExpressionEvaluationException(
("No association definition variable in %s; the expression may be used in a wrong place. "
+ "It is only supposed to create an association.").formatted(
context.getContextDescription()));
}
return associationDefinition;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,8 @@
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.cache.CacheType;
import com.evolveum.midpoint.schema.constants.ExpressionConstants;
import com.evolveum.midpoint.schema.expression.TypedValue;
import com.evolveum.midpoint.schema.expression.VariablesMap;
import com.evolveum.midpoint.schema.internals.InternalsConfig;
import com.evolveum.midpoint.schema.processor.ResourceObjectTypeDefinition;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.ShadowUtil;
import com.evolveum.midpoint.task.api.Task;
Expand All @@ -47,6 +44,8 @@
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType;

import static com.evolveum.midpoint.model.common.expression.evaluator.AssociationRelatedEvaluatorUtil.getAssociationDefinition;

/**
* Creates an association (or associations) based on specified condition for the associated object.
*
Expand Down Expand Up @@ -116,28 +115,31 @@ protected PrismContainerValue<ShadowAssociationType> createResultValue(
return associationCVal;
}

private ResourceObjectTypeDefinition associationTargetDef(ExpressionEvaluationContext params) throws ExpressionEvaluationException {
var rAssocTargetDefTypedValue = (TypedValue<ResourceObjectTypeDefinition>)
params.getVariables().get(ExpressionConstants.VAR_ASSOCIATION_TARGET_OBJECT_CLASS_DEFINITION);
if (rAssocTargetDefTypedValue == null || rAssocTargetDefTypedValue.getValue() == null) {
throw new ExpressionEvaluationException(
String.format("No association target object definition variable in %s; the expression may be used in"
+ " a wrong place. It is only supposed to create an association.",
params.getContextDescription()));
}
return (ResourceObjectTypeDefinition) rAssocTargetDefTypedValue.getValue();
}

@Override
protected ObjectQuery extendQuery(ObjectQuery query, ExpressionEvaluationContext params)
protected ObjectQuery extendQuery(ObjectQuery query, ExpressionEvaluationContext context)
throws ExpressionEvaluationException {
@SuppressWarnings("unchecked")
var rAssocTargetDef = associationTargetDef(params);
ObjectFilter coordinatesFilter = prismContext.queryFor(ShadowType.class)
.item(ShadowType.F_RESOURCE_REF).ref(rAssocTargetDef.getResourceOid())
.and().item(ShadowType.F_KIND).eq(rAssocTargetDef.getKind())
.and().item(ShadowType.F_INTENT).eq(rAssocTargetDef.getIntent())
.buildFilter();

var associationDefinition = getAssociationDefinition(context);

ObjectFilter coordinatesFilter;
var coordinatesFilterBuilder = prismContext.queryFor(ShadowType.class)
.item(ShadowType.F_RESOURCE_REF).ref(associationDefinition.getResourceOid());

if (!associationDefinition.hasMultipleIntents()) {
var associationTargetDef = associationDefinition.getAssociationTarget(); // there should be exactly one
coordinatesFilter = coordinatesFilterBuilder
.and().item(ShadowType.F_KIND).eq(associationTargetDef.getKind())
.and().item(ShadowType.F_INTENT).eq(associationTargetDef.getIntent())
.buildFilter();
} else {
// There are multiple intents here. Unfortunately, we cannot use them as filtering criteria, because of the
// provisioning module limitations: only one kind/intent is allowed. So, we'll search for all the objects
// of the given object class, as it was done before 4.6 (see commit 473467d303225b207a2f8da820ee08f7cc786791).
// We'll filter out unwanted objects later in isAcceptable() method.
coordinatesFilter = coordinatesFilterBuilder
.and().item(ShadowType.F_OBJECT_CLASS).eq(associationDefinition.getObjectClassName())
.buildFilter();
}
query.setFilter(
prismContext.queryFactory()
.createAnd(coordinatesFilter, query.getFilter()));
Expand All @@ -157,8 +159,18 @@ protected void extendOptions(
}

@Override
protected boolean isAcceptable(@NotNull PrismObject<ShadowType> object) {
return ShadowUtil.isNotDead(object.asObjectable());
protected boolean isAcceptable(@NotNull PrismObject<ShadowType> object, ExpressionEvaluationContext context)
throws ExpressionEvaluationException {
if (ShadowUtil.isDead(object.asObjectable())) {
return false;
}
var associationDefinition = getAssociationDefinition(context);
if (!associationDefinition.hasMultipleIntents()) {
return true; // we searched for specific kind+intent (see above)
}
var shadow = object.asObjectable();
return shadow.getKind() == associationDefinition.getKind()
&& associationDefinition.getIntents().contains(shadow.getIntent());
}

/**
Expand All @@ -179,17 +191,16 @@ protected CacheInfo getCacheInfo() {
ShadowType.class);
}

protected ObjectQuery createRawQuery(ExpressionEvaluationContext params) throws ConfigurationException, SchemaException, ExpressionEvaluationException {
protected ObjectQuery createRawQuery(ExpressionEvaluationContext context)
throws ConfigurationException, SchemaException, ExpressionEvaluationException {
SearchFilterType filterBean =
MiscUtil.configNonNull(expressionEvaluatorBean.getFilter(), () -> "No filter in " + shortDebugDump());

var associationTargetDef = associationTargetDef(params);
var concreteShadowDef = associationTargetDef.getPrismObjectDefinition();
var associationTargetDef = getAssociationDefinition(context);
var concreteShadowDef = associationTargetDef.getAssociationTarget().getPrismObjectDefinition();
var filter = prismContext.getQueryConverter().createObjectFilter(concreteShadowDef, filterBean);
return prismContext.queryFactory().createQuery(filter);
};


};
}

Expand Down

0 comments on commit 189d8f6

Please sign in to comment.