/* * Copyright (c) 2010-2014 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.evolveum.midpoint.web.page.admin.users; import com.evolveum.midpoint.model.api.ProgressInformation; import com.evolveum.midpoint.model.api.ProgressListener; import com.evolveum.midpoint.model.api.context.ModelContext; import com.evolveum.midpoint.model.api.context.ModelElementContext; import com.evolveum.midpoint.model.api.context.ModelProjectionContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.ObjectDeltaOperation; import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.processor.ResourceAttribute; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.result.OperationResultStatus; import com.evolveum.midpoint.schema.util.ShadowUtil; 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.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.exception.SecurityViolationException; 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.progress.ProgressDto; import com.evolveum.midpoint.web.component.progress.ProgressReportActivityDto; import com.evolveum.midpoint.web.component.progress.ProgressReportingAwarePage; import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultStatusType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import org.apache.commons.lang.StringUtils; import org.jetbrains.annotations.NotNull; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import static com.evolveum.midpoint.model.api.ProgressInformation.ActivityType.FOCUS_OPERATION; import static com.evolveum.midpoint.model.api.ProgressInformation.ActivityType.RESOURCE_OBJECT_OPERATION; import static com.evolveum.midpoint.model.api.ProgressInformation.StateType; import static com.evolveum.midpoint.model.api.ProgressInformation.StateType.ENTERING; import static com.evolveum.midpoint.model.api.ProgressInformation.StateType.EXITING; import static com.evolveum.midpoint.web.component.progress.ProgressReportActivityDto.ResourceOperationResult; /** * @author mederly */ public class DefaultGuiProgressListener implements ProgressListener, Serializable { private static final Trace LOGGER = TraceManager.getTrace(DefaultGuiProgressListener.class); private ProgressDto progressDto; private ProgressReportingAwarePage parentPage; private boolean abortRequested; public DefaultGuiProgressListener(ProgressReportingAwarePage parentPage, ProgressDto progressDto) { this.parentPage = parentPage; this.progressDto = progressDto; } @Override public void onProgressAchieved(ModelContext modelContext, ProgressInformation progressInformation) { if (LOGGER.isTraceEnabled()) { LOGGER.trace("onProgressAchieved: {}\n, modelContext = \n{}", new Object[]{progressInformation.debugDump(), modelContext.debugDump(2)}); } if (progressDto == null) { LOGGER.error("No progressDto, exiting"); // should not occur return; } if (StringUtils.isNotEmpty(progressInformation.getMessage())) { progressDto.log(progressInformation.getMessage()); } List<ProgressReportActivityDto> progressReportActivities = progressDto.getProgressReportActivities(); if (progressInformation != null) { ProgressReportActivityDto si = findRelevantStatusItem(progressReportActivities, progressInformation); if (si == null) { progressDto.add(createStatusItem(progressInformation, modelContext)); } else { updateStatusItemState(si, progressInformation, modelContext); } } addExpectedStatusItems(progressReportActivities, modelContext); } @Override public boolean isAbortRequested() { return abortRequested; } public void setAbortRequested(boolean value) { this.abortRequested = value; } private void addExpectedStatusItems(List<ProgressReportActivityDto> progressReportActivities, ModelContext modelContext) { if (modelContext.getFocusContext() != null) { ModelElementContext fc = modelContext.getFocusContext(); if (isNotEmpty(fc.getPrimaryDelta()) || isNotEmpty(fc.getSecondaryDelta())) { ProgressInformation modelStatus = new ProgressInformation(FOCUS_OPERATION, (StateType) null); if (findRelevantStatusItem(progressReportActivities, modelStatus) == null) { progressReportActivities.add(createStatusItem(modelStatus, modelContext)); } } } if (modelContext.getProjectionContexts() != null) { Collection<ModelProjectionContext> projectionContexts = modelContext.getProjectionContexts(); for (ModelProjectionContext mpc : projectionContexts) { ProgressInformation projectionStatus = new ProgressInformation(RESOURCE_OBJECT_OPERATION, mpc.getResourceShadowDiscriminator(), (StateType) null); if (findRelevantStatusItem(progressReportActivities, projectionStatus) == null) { progressReportActivities.add(createStatusItem(projectionStatus, modelContext)); } } } } private boolean isNotEmpty(ObjectDelta delta) { return delta != null && !delta.isEmpty(); } private ProgressReportActivityDto findRelevantStatusItem(List<ProgressReportActivityDto> progressReportActivities, ProgressInformation progressInformation) { for (ProgressReportActivityDto si : progressReportActivities) { if (si.correspondsTo(progressInformation)) { return si; } } return null; } private void updateStatusItemState(ProgressReportActivityDto si, ProgressInformation progressInformation, ModelContext modelContext) { si.setActivityType(progressInformation.getActivityType()); si.setResourceShadowDiscriminator(progressInformation.getResourceShadowDiscriminator()); if (progressInformation.getResourceShadowDiscriminator() != null) { String resourceOid = progressInformation.getResourceShadowDiscriminator().getResourceOid(); String resourceName = resourceOid != null ? getResourceName(resourceOid) : ""; si.setResourceName(resourceName); } if (progressInformation.getStateType() == null) { si.setStatus(null); } else if (progressInformation.getStateType() == ENTERING) { si.setStatus(OperationResultStatusType.IN_PROGRESS); } else { OperationResult result = progressInformation.getOperationResult(); if (result != null) { OperationResultStatus status = result.getStatus(); if (status == OperationResultStatus.UNKNOWN) { status = result.getComputeStatus(); } si.setStatus(status.createStatusType()); } else { si.setStatus(OperationResultStatusType.UNKNOWN); } } // information about modifications on a resource if (progressInformation.getActivityType() == RESOURCE_OBJECT_OPERATION && progressInformation.getStateType() == EXITING && progressInformation.getResourceShadowDiscriminator() != null && progressInformation.getResourceShadowDiscriminator().getResourceOid() != null) { ModelProjectionContext mpc = modelContext.findProjectionContext(progressInformation.getResourceShadowDiscriminator()); if (mpc != null) { // it shouldn't be null! // operations performed (TODO aggregate them somehow?) List<ResourceOperationResult> resourceOperationResultList = new ArrayList<>(); List<? extends ObjectDeltaOperation> executedDeltas = mpc.getExecutedDeltas(); for (ObjectDeltaOperation executedDelta : executedDeltas) { ObjectDelta delta = executedDelta.getObjectDelta(); if (delta != null) { OperationResult r = executedDelta.getExecutionResult(); OperationResultStatus status = r.getStatus(); if (status == OperationResultStatus.UNKNOWN) { status = r.getComputeStatus(); } resourceOperationResultList.add(new ResourceOperationResult(delta.getChangeType(), status)); } } si.setResourceOperationResultList(resourceOperationResultList); // object name PrismObject<ShadowType> object = mpc.getObjectNew(); if (object == null) { object = mpc.getObjectOld(); } String name = null; if (object != null) { if (object.asObjectable().getName() != null) { name = PolyString.getOrig(object.asObjectable().getName()); } else { // determine from attributes ResourceAttribute nameAttribute = ShadowUtil.getNamingAttribute(object); if (nameAttribute != null) { name = String.valueOf(nameAttribute.getAnyRealValue()); } } } if (name != null) { si.setResourceObjectName(name); } } } } private ProgressReportActivityDto createStatusItem(ProgressInformation progressInformation, ModelContext modelContext) { ProgressReportActivityDto si = new ProgressReportActivityDto(); updateStatusItemState(si, progressInformation, modelContext); return si; } private Map<String,String> nameCache = new HashMap<>(); private String getResourceName(@NotNull String oid) { String name = nameCache.get(oid); if (name != null) { return name; } Task task = parentPage.createSimpleTask("getResourceName"); OperationResult result = new OperationResult("getResourceName"); Collection<SelectorOptions<GetOperationOptions>> raw = SelectorOptions.createCollection(GetOperationOptions.createRaw()); // todo what about security? try { PrismObject<ResourceType> object = parentPage.getModelService().getObject(ResourceType.class, oid, raw, task, result); name = PolyString.getOrig(object.asObjectable().getName()); } catch (ObjectNotFoundException|SchemaException|SecurityViolationException|CommunicationException|ConfigurationException e) { LoggingUtils.logUnexpectedException(LOGGER, "Couldn't determine the name of resource {}", e, oid); name = "(" + oid + ")"; } nameCache.put(oid, name); return name; } }