Skip to content

Commit

Permalink
Merge branch 'master' of github.com:Evolveum/midpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Mar 26, 2015
2 parents b3df3ed + ae00e24 commit 404a10f
Show file tree
Hide file tree
Showing 41 changed files with 1,080 additions and 438 deletions.
Expand Up @@ -102,7 +102,9 @@ public static <T extends Objectable> ObjectDelta<T> createObjectDelta(ObjectDelt
ObjectType objectToAddElement = objectDeltaType.getObjectToAdd();
// PrismObject<T> objectToAdd = prismContext.getXnodeProcessor().parseObject(objectToAddElement.getXnode());
// PrismObject<T> objectToAdd = prismContext.getJaxbDomHack().parseObjectFromJaxb(objectToAddElement);
objectDelta.setObjectToAdd(objectToAddElement.asPrismObject());
if (objectToAddElement != null) {
objectDelta.setObjectToAdd(objectToAddElement.asPrismObject());
}
return objectDelta;
} else if (objectDeltaType.getChangeType() == ChangeTypeType.MODIFY) {
ObjectDelta<T> objectDelta = new ObjectDelta<T>(type, ChangeType.MODIFY, prismContext);
Expand Down
17 changes: 15 additions & 2 deletions infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd
Expand Up @@ -6513,6 +6513,9 @@
For explicitness, only one of approverRef(s)/approverExpression(s),
approvalSchema and approvalProcess should be specified.
</p>
<p>
THIS PROPERTY (approvalProcess) IS NOT SUPPORTED YET.
</p>
</xsd:documentation>
</xsd:annotation>
</xsd:element>
Expand Down Expand Up @@ -10027,6 +10030,7 @@
<xsd:annotation>
<xsd:documentation>
Order in which the change processor should be invoked. (Unspecified means "at the end".)
NOT IMPLEMENTED YET.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
Expand Down Expand Up @@ -10111,8 +10115,9 @@
<xsd:element name="addRoleAssignmentAspect" type="tns:PcpAspectConfigurationType" minOccurs="0" />
<xsd:element name="modifyRoleAssignmentAspect" type="tns:PcpAspectConfigurationType" minOccurs="0" />
<xsd:element name="addResourceAssignmentAspect" type="tns:PcpAspectConfigurationType" minOccurs="0" />
<xsd:element name="addRoleAspect" type="tns:PcpAspectConfigurationType" minOccurs="0" />
<xsd:element name="modifyRoleAspect" type="tns:PcpAspectConfigurationType" minOccurs="0" />
<xsd:element name="modifyResourceAssignmentAspect" type="tns:PcpAspectConfigurationType" minOccurs="0" />
<xsd:element name="addAbstractRoleAspect" type="tns:PcpAspectConfigurationType" minOccurs="0" />
<xsd:element name="modifyAbstractRoleAspect" type="tns:PcpAspectConfigurationType" minOccurs="0" />
<xsd:element name="addUserAspect" type="tns:PcpAspectConfigurationType" minOccurs="0" />
<xsd:element name="modifyUserAspect" type="tns:PcpAspectConfigurationType" minOccurs="0" />
<xsd:element name="addResourceAspect" type="tns:PcpAspectConfigurationType" minOccurs="0" />
Expand All @@ -10132,6 +10137,12 @@
They take all the approver information directly from the object (role or resource) being assigned.
However, there are some others (namely, role/resource/user/whatever add/modify aspects) that need
the explicit information about approver(s) in order to know where to route the request.

For the former aspects, the approver information specified here takes precedence over
approver information derived from the objects being used (e.g. role or resource).
More specifically, if any approver information is here, no approver information is
taken from the objects. This could be changed (e.g. by allowing to tune this behavior)
in the future.
</xsd:documentation>
<xsd:appinfo>
<a:container/>
Expand Down Expand Up @@ -10180,6 +10191,8 @@

For explicitness, only one of approverRef(s)/approverExpression(s),
approvalSchema and approvalProcess should be specified.

THIS PROPERTY (approvalProcess) IS NOT SUPPORTED YET.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
Expand Down
Expand Up @@ -417,4 +417,45 @@
</xsd:complexType>
<xsd:element name="resourceAssignmentModificationApprovalFormType" type="tns:ResourceAssignmentModificationApprovalFormType" substitutionGroup="c:object"/>

<xsd:complexType name="AddObjectApprovalFormType">
<xsd:annotation>
<xsd:documentation>
TODO
</xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="tns:QuestionFormType">
<xsd:sequence>
<xsd:element name="objectToAdd" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<a:displayName>Object to be added</a:displayName>
<a:displayOrder>100</a:displayOrder>
<a:access>read</a:access>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="requesterComment" type="xsd:string" minOccurs="0">
<xsd:annotation>
<xsd:appinfo>
<a:displayName>Requester's comment</a:displayName>
<a:displayOrder>110</a:displayOrder>
<a:access>read</a:access>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="comment" type="xsd:string" minOccurs="0">
<xsd:annotation>
<xsd:appinfo>
<a:displayName>Your comment</a:displayName>
<a:displayOrder>120</a:displayOrder>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:element name="addObjectApprovalFormType" type="tns:AddObjectApprovalFormType" substitutionGroup="c:object"/>

</xsd:schema>
Expand Up @@ -236,6 +236,7 @@ private void extractTemplate(File dst, String templateName) throws IOException,
}

templateRoot = new File(DATA_TEMPLATE_DIR, templateName);
String templateRootPath = DATA_TEMPLATE_DIR + "/" + templateName; // templateRoot.getPath does not work on Windows, as it puts "\" into the path name (leading to problems with getSystemResource)

// Determing if we need to extract from JAR or directory
if (templateRoot.isDirectory()) {
Expand All @@ -244,7 +245,6 @@ private void extractTemplate(File dst, String templateName) throws IOException,
return;
}

String templateRootPath = templateRoot.getPath();
LOGGER.debug("Try to localize OpenDJ Template in JARs as " + templateRootPath);

URL srcUrl = ClassLoader.getSystemResource(templateRootPath);
Expand Down
Expand Up @@ -21,9 +21,11 @@
import com.evolveum.midpoint.common.refinery.ResourceShadowDiscriminator;
import com.evolveum.midpoint.model.api.ProgressInformation;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.delta.DeltaSetTriple;
import com.evolveum.midpoint.util.DebugDumpable;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType;

/**
* @author semancik
Expand All @@ -46,4 +48,6 @@ public interface ModelContext<F extends ObjectType> extends Serializable, DebugD
DeltaSetTriple<? extends EvaluatedAssignment> getEvaluatedAssignmentTriple();

PrismContext getPrismContext(); // use with care

PrismObject<SystemConfigurationType> getSystemConfiguration(); // beware, may be null - use only as a performance optimization
}
Expand Up @@ -99,7 +99,7 @@ private void processEvent(WorkflowEvent event, OperationResult result) {
notificationManager.processEvent(event);
} catch (RuntimeException e) {
result.recordFatalError("An unexpected exception occurred when preparing and sending notifications: " + e.getMessage(), e);
LoggingUtils.logException(LOGGER, "An unexpected exception occurred when preparing and sending notifications: " + e.getMessage(), e);
LoggingUtils.logUnexpectedException(LOGGER, "An unexpected exception occurred when preparing and sending notifications: " + e.getMessage(), e);
}

// todo work correctly with operationResult (in whole notification module)
Expand All @@ -113,7 +113,7 @@ private void processEvent(WorkflowEvent event) {
try {
notificationManager.processEvent(event);
} catch (RuntimeException e) {
LoggingUtils.logException(LOGGER, "An unexpected exception occurred when preparing and sending notifications: " + e.getMessage(), e);
LoggingUtils.logUnexpectedException(LOGGER, "An unexpected exception occurred when preparing and sending notifications: " + e.getMessage(), e);
}
}
}
Expand Up @@ -24,6 +24,7 @@
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.wf.impl.processors.BaseChangeProcessor;
import com.evolveum.midpoint.wf.impl.processors.ChangeProcessor;

import org.apache.commons.configuration.Configuration;
Expand Down Expand Up @@ -53,7 +54,7 @@ public class WfConfiguration implements BeanFactoryAware {
private static final transient Trace LOGGER = TraceManager.getTrace(WfConfiguration.class);

private static final String WF_CONFIG_SECTION = "midpoint.workflow";
private static final String CHANGE_PROCESSORS_SECTION = "changeProcessors";
private static final String CHANGE_PROCESSORS_SECTION = "changeProcessors"; // deprecated

public static final String KEY_ENABLED = "enabled";
public static final String KEY_JDBC_DRIVER = "jdbcDriver";
Expand All @@ -68,9 +69,11 @@ public class WfConfiguration implements BeanFactoryAware {

public static final List<String> KNOWN_KEYS = Arrays.asList("midpoint.home", KEY_ENABLED, KEY_JDBC_DRIVER, KEY_JDBC_URL,
KEY_JDBC_USERNAME, KEY_JDBC_PASSWORD, KEY_DATA_SOURCE, KEY_ACTIVITI_SCHEMA_UPDATE, KEY_PROCESS_CHECK_INTERVAL,
KEY_AUTO_DEPLOYMENT_FROM, KEY_ALLOW_APPROVE_OTHERS_ITEMS, CHANGE_PROCESSORS_SECTION);
KEY_AUTO_DEPLOYMENT_FROM, KEY_ALLOW_APPROVE_OTHERS_ITEMS);

@Autowired(required = true)
public static final List<String> DEPRECATED_KEYS = Arrays.asList(CHANGE_PROCESSORS_SECTION);

@Autowired
private MidpointConfiguration midpointConfiguration;

private BeanFactory beanFactory;
Expand All @@ -95,7 +98,7 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {

private boolean allowApproveOthersItems;

private List<ChangeProcessor> changeProcessors = null;
private List<ChangeProcessor> changeProcessors = new ArrayList<>();

private int processCheckInterval;
private String[] autoDeploymentFrom;
Expand All @@ -105,7 +108,7 @@ void initialize() {

Configuration c = midpointConfiguration.getConfiguration(WF_CONFIG_SECTION);

checkAllowedKeys(c, KNOWN_KEYS);
checkAllowedKeys(c, KNOWN_KEYS, DEPRECATED_KEYS);

enabled = c.getBoolean(KEY_ENABLED, true);
if (!enabled) {
Expand Down Expand Up @@ -180,8 +183,9 @@ void initialize() {
validate();
}

public void checkAllowedKeys(Configuration c, List<String> knownKeys) {
Set<String> knownKeysSet = new HashSet<String>(knownKeys);
public void checkAllowedKeys(Configuration c, List<String> knownKeys, List<String> deprecatedKeys) {
Set<String> knownKeysSet = new HashSet<>(knownKeys);
Set<String> deprecatedKeysSet = new HashSet<>(deprecatedKeys);

Iterator<String> keyIterator = c.getKeys();
while (keyIterator.hasNext()) {
Expand All @@ -192,6 +196,9 @@ public void checkAllowedKeys(Configuration c, List<String> knownKeys) {
if (colon != -1) {
normalizedKeyName = normalizedKeyName.substring(colon + 1);
}
if (deprecatedKeysSet.contains(keyName) || deprecatedKeysSet.contains(normalizedKeyName)) {
throw new SystemException("Deprecated key " + keyName + " in workflow configuration. Please see https://wiki.evolveum.com/display/midPoint/Workflow+configuration.");
}
if (!knownKeysSet.contains(keyName) && !knownKeysSet.contains(normalizedKeyName)) { // ...we need to test both because of keys like 'midpoint.home'
throw new SystemException("Unknown key " + keyName + " in workflow configuration");
}
Expand Down Expand Up @@ -267,51 +274,21 @@ public boolean isAllowApproveOthersItems() {
return allowApproveOthersItems;
}

public synchronized List<ChangeProcessor> getChangeProcessors() {
if (changeProcessors != null) {
return changeProcessors;
}

changeProcessors = new ArrayList<ChangeProcessor>();

if (!enabled) {
return changeProcessors;
}

List<String> changeProcessorNames = new ArrayList<String>(); // list - to preserve order

Iterator<String> cpIterator = getChangeProcessorsConfig().getKeys(); // returns 'processor-name' but also 'other-processor-name.aspect-name' etc.
while (cpIterator.hasNext()) {
String keyName = cpIterator.next();
String processorName = StringUtils.substringBefore(keyName, ".");
if (!changeProcessorNames.contains(processorName)) {
changeProcessorNames.add(processorName);
}
}

LOGGER.trace("Resolving change processors: {}", changeProcessorNames);

for (String processorName : changeProcessorNames) {
LOGGER.trace("Searching for change processor {}", processorName);
try {
ChangeProcessor processor = (ChangeProcessor) beanFactory.getBean(processorName);
changeProcessors.add(processor);
} catch(BeansException e) {
throw new SystemException("Change processor " + processorName + " could not be found.", e);
}
}

LOGGER.debug("Resolved " + changeProcessors.size() + " change processors.");
return changeProcessors;
}

public ChangeProcessor findChangeProcessor(String processorClassName) {
for (ChangeProcessor cp : getChangeProcessors()) {
for (ChangeProcessor cp : changeProcessors) {
if (processorClassName.equals(cp.getClass().getName())) {
return cp;
}
}

throw new IllegalStateException("Change processor " + processorClassName + " is not registered.");
}

public void registerProcessor(ChangeProcessor changeProcessor) {
changeProcessors.add(changeProcessor);
}

public List<ChangeProcessor> getChangeProcessors() {
return changeProcessors;
}
}
Expand Up @@ -30,8 +30,11 @@
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.wf.impl.processors.BaseConfigurationHelper;
import com.evolveum.midpoint.wf.impl.processors.ChangeProcessor;

import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType;
import org.apache.commons.lang.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
Expand All @@ -57,6 +60,9 @@ public class WfHook implements ChangeHook {
@Autowired
private WfConfiguration wfConfiguration;

@Autowired
private BaseConfigurationHelper baseConfigurationHelper;

@Autowired
private HookRegistry hookRegistry;

Expand Down Expand Up @@ -84,11 +90,30 @@ public HookOperationMode invoke(ModelContext context, Task task, OperationResult
result.addParam("taskFromModel", task.toString());
result.addContext("model state", context.getState());

WfConfigurationType wfConfigurationType = baseConfigurationHelper.getWorkflowConfiguration(context, result);
if (wfConfigurationType == null) { // should not occur, but ... (e.g. when initially loading objects into repository; if done in non-raw mode)
LOGGER.warn("No system configuration. Workflow approvals are disabled. Proceeding with operation execution as if everything is approved.");
result.recordSuccess();
return HookOperationMode.FOREGROUND;
}
if (Boolean.FALSE.equals(wfConfigurationType.isModelHookEnabled())) {
LOGGER.info("Workflow model hook is disabled. Proceeding with operation execution as if everything is approved.");
result.recordSuccess();
return HookOperationMode.FOREGROUND;
}

logOperationInformation(context);

HookOperationMode retval = processModelInvocation(context, task, result);
result.recordSuccessIfUnknown();
return retval;
try {
HookOperationMode retval = processModelInvocation(context, wfConfigurationType, task, result);
result.recordSuccessIfUnknown();
return retval;
} catch (RuntimeException e) {
if (result.isUnknown()) {
result.recordFatalError("Couldn't process model invocation in workflow module: " + e.getMessage(), e);
}
throw e;
}
}

@Override
Expand Down Expand Up @@ -123,7 +148,7 @@ private void logOperationInformation(ModelContext context) {
}
}

HookOperationMode processModelInvocation(ModelContext context, Task taskFromModel, OperationResult result) {
HookOperationMode processModelInvocation(ModelContext<? extends ObjectType> context, WfConfigurationType wfConfigurationType, Task taskFromModel, OperationResult result) {

try {

Expand All @@ -133,12 +158,8 @@ HookOperationMode processModelInvocation(ModelContext context, Task taskFromMode
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Trying change processor: " + changeProcessor.getClass().getName());
}
if (!changeProcessor.isEnabled()) {
LOGGER.trace("It is disabled, continuing with next one.");
continue;
}
try {
HookOperationMode hookOperationMode = changeProcessor.processModelInvocation(context, taskFromModel, result);
HookOperationMode hookOperationMode = changeProcessor.processModelInvocation(context, wfConfigurationType, taskFromModel, result);
if (hookOperationMode != null) {
return hookOperationMode;
}
Expand Down Expand Up @@ -168,5 +189,4 @@ HookOperationMode processModelInvocation(ModelContext context, Task taskFromMode
return HookOperationMode.FOREGROUND;
}


}

0 comments on commit 404a10f

Please sign in to comment.