/** @author semancik */ public class ReflectionXPathFunctionResolver implements XPathFunctionResolver { private static final Object LOG_FUNCTION_NAME = "logDebug"; public static final Trace LOGGER = TraceManager.getTrace(ReflectionXPathFunctionResolver.class); private Collection<FunctionLibrary> functions; public ReflectionXPathFunctionResolver(Collection<FunctionLibrary> functions) { super(); this.functions = functions; } /* (non-Javadoc) * @see javax.xml.xpath.XPathFunctionResolver#resolveFunction(javax.xml.namespace.QName, int) */ @Override public XPathFunction resolveFunction(QName functionQName, int arity) { boolean enableDebug = false; String namespace = functionQName.getNamespaceURI(); if (StringUtils.isEmpty(namespace)) { namespace = MidPointConstants.NS_FUNC_BASIC; enableDebug = true; } else if (namespace.equals(MidPointConstants.NS_FUNC_BASIC)) { enableDebug = true; } FunctionLibrary lib = findLibrary(namespace); if (lib == null) { LOGGER.trace( "Unknown namespace for function {} function with {} arguments", functionQName, arity); return null; } Object functionObject = null; if (lib.getXmlFunctions() != null) { functionObject = lib.getXmlFunctions(); } else { functionObject = lib.getGenericFunctions(); } String functionName = functionQName.getLocalPart(); LOGGER.trace("Resolving to {} function with {} arguments", functionName, arity); ReflectionXPathFunctionWrapper xPathFunction = new ReflectionXPathFunctionWrapper(functionObject, functionName, arity, enableDebug); return xPathFunction; } private FunctionLibrary findLibrary(String namespace) { for (FunctionLibrary lib : functions) { if (lib.getNamespace().equals(namespace)) { return lib; } } return null; } }
/** @author mederly */ public class MidPointTaskListener implements TaskListener { private static final Trace LOGGER = TraceManager.getTrace(MidPointTaskListener.class); private static final String DOT_CLASS = MidPointTaskListener.class.getName() + "."; @Override public void notify(DelegateTask delegateTask) { if (LOGGER.isTraceEnabled()) { LOGGER.trace( "notify called; event name = {}, name = {}", delegateTask.getEventName(), delegateTask.getName()); } ActivitiInterface activitiInterface = SpringApplicationContextHolder.getActivitiInterface(); activitiInterface.notifyMidpointAboutTaskEvent(delegateTask); } }
/** * Generic change aspect for adding a resource assignment to (any) focus type. * * @author mederly */ @Component public abstract class AddResourceAssignmentAspect<F extends FocusType> extends AddAssignmentAspect<ResourceType, F> { private static final Trace LOGGER = TraceManager.getTrace(AddResourceAssignmentAspect.class); @Autowired protected ResourceAssignmentHelper specificAssignmentHelper; @Override public boolean isEnabledByDefault() { return true; } @Override protected boolean isAssignmentRelevant(AssignmentType assignmentType) { return specificAssignmentHelper.isResourceAssignment(assignmentType); } @Override protected boolean shouldAssignmentBeApproved( PcpAspectConfigurationType config, ResourceType resourceType) { return specificAssignmentHelper.shouldAssignmentBeApproved(config, resourceType); } @Override protected ApprovalRequest<AssignmentType> createApprovalRequest( PcpAspectConfigurationType config, AssignmentType assignmentType, ResourceType resourceType) { return specificAssignmentHelper.createApprovalRequest(config, assignmentType, resourceType); } @Override protected ResourceType getAssignmentApprovalTarget( AssignmentType assignmentType, OperationResult result) { return specificAssignmentHelper.getAssignmentApprovalTarget(assignmentType, result); } @Override protected AssignmentType cloneAndCanonicalizeAssignment(AssignmentType assignmentType) { return specificAssignmentHelper.cloneAndCanonicalizeAssignment(assignmentType); } }
@Component public class PasswordPolicyProcessor { private static final Trace LOGGER = TraceManager.getTrace(PasswordPolicyProcessor.class); @Autowired(required = true) Protector protector; @Autowired(required = true) ModelObjectResolver resolver; void processPasswordPolicy( ValuePolicyType passwordPolicy, PrismProperty password, OperationResult result) throws PolicyViolationException, SchemaException { if (passwordPolicy == null) { LOGGER.trace("Skipping processing password policies. Password policy not specified."); return; } String passwordValue = determinePasswordValue(password); boolean isValid = PasswordPolicyUtils.validatePassword(passwordValue, passwordPolicy, result); if (!isValid) { result.computeStatus(); throw new PolicyViolationException( "Provided password does not satisfy password policies. " + result.getMessage()); } } <F extends FocusType> void processPasswordPolicy( LensFocusContext<F> focusContext, LensContext<F> context, Task task, OperationResult result) throws PolicyViolationException, SchemaException { if (!UserType.class.isAssignableFrom(focusContext.getObjectTypeClass())) { LOGGER.trace("Skipping processing password policies because focus is not user"); return; } // PrismProperty<PasswordType> password = getPassword(focusContext); ObjectDelta userDelta = focusContext.getDelta(); if (userDelta == null) { LOGGER.trace("Skipping processing password policies. User delta not specified."); return; } if (userDelta.isDelete()) { LOGGER.trace("Skipping processing password policies. User will be deleted."); return; } PrismProperty<PasswordType> password = null; PrismObject<F> user; if (ChangeType.ADD == userDelta.getChangeType()) { user = focusContext.getDelta().getObjectToAdd(); if (user != null) { password = user.findProperty(SchemaConstants.PATH_PASSWORD_VALUE); } if (password == null) { if (wasExecuted(userDelta, focusContext)) { LOGGER.trace( "Skipping processing password policies. User addition was already executed."); return; } } } else if (ChangeType.MODIFY == userDelta.getChangeType()) { PropertyDelta<PasswordType> passwordValueDelta; if (userDelta != null) { passwordValueDelta = userDelta.findPropertyDelta(SchemaConstants.PATH_PASSWORD_VALUE); if (passwordValueDelta == null) { LOGGER.trace( "Skipping processing password policies. User delta does not contain password change."); return; } if (userDelta.getChangeType() == ChangeType.MODIFY && passwordValueDelta != null) { if (passwordValueDelta.isAdd()) { password = (PrismProperty<PasswordType>) passwordValueDelta.getItemNewMatchingPath(null); } else if (passwordValueDelta.isDelete()) { password = null; } else { password = (PrismProperty<PasswordType>) passwordValueDelta.getItemNewMatchingPath(null); } } else { password = (PrismProperty<PasswordType>) passwordValueDelta.getItemNewMatchingPath(null); } } } ValuePolicyType passwordPolicy; if (focusContext.getOrgPasswordPolicy() == null) { passwordPolicy = determineValuePolicy(userDelta, focusContext.getObjectAny(), context, task, result); focusContext.setOrgPasswordPolicy(passwordPolicy); } else { passwordPolicy = focusContext.getOrgPasswordPolicy(); } processPasswordPolicy(passwordPolicy, password, result); } private <F extends FocusType> boolean wasExecuted( ObjectDelta<UserType> userDelta, LensFocusContext<F> focusContext) { for (LensObjectDeltaOperation<F> executedDeltaOperation : focusContext.getExecutedDeltas()) { ObjectDelta<F> executedDelta = executedDeltaOperation.getObjectDelta(); if (!executedDelta.isAdd()) { continue; } else if (executedDelta.getObjectToAdd() != null && executedDelta.getObjectTypeClass().equals(UserType.class)) { return true; } } return false; } // TODO: maybe some caching of orgs????? private <T extends ObjectType, F extends ObjectType> ValuePolicyType determineValuePolicy( ObjectDelta<UserType> userDelta, PrismObject<T> object, LensContext<F> context, Task task, OperationResult result) throws SchemaException { // check the modification of organization first ValuePolicyType valuePolicy = determineValuePolicy(userDelta, task, result); // if null, check the existing organization if (valuePolicy == null) { valuePolicy = determineValuePolicy(object, task, result); } // if still null, just use global policy if (valuePolicy == null) { valuePolicy = context.getEffectivePasswordPolicy(); } if (valuePolicy != null) { LOGGER.trace( "Value policy {} will be user to check password.", valuePolicy.getName().getOrig()); } return valuePolicy; } private ValuePolicyType determineValuePolicy( ObjectDelta<UserType> userDelta, Task task, OperationResult result) throws SchemaException { ReferenceDelta orgDelta = userDelta.findReferenceModification(UserType.F_PARENT_ORG_REF); ValuePolicyType passwordPolicy = null; LOGGER.trace("Determining password policy from org delta."); if (orgDelta != null) { PrismReferenceValue orgRefValue = orgDelta.getAnyValue(); try { PrismObject<OrgType> org = resolver.resolve(orgRefValue, "resolving parent org ref", null, null, result); OrgType orgType = org.asObjectable(); ObjectReferenceType ref = orgType.getPasswordPolicyRef(); if (ref != null) { LOGGER.trace("Org {} has specified password policy.", orgType); passwordPolicy = resolver.resolve( ref, ValuePolicyType.class, null, "resolving password policy for organization", task, result); LOGGER.trace("Resolved password policy {}", passwordPolicy); } if (passwordPolicy == null) { passwordPolicy = determineValuePolicy(org, task, result); } } catch (ObjectNotFoundException e) { throw new IllegalStateException(e); } } return passwordPolicy; } private ValuePolicyType determineValuePolicy( PrismObject object, Task task, OperationResult result) throws SchemaException { LOGGER.trace("Determining password policies from object", object); PrismReference orgRef = object.findReference(ObjectType.F_PARENT_ORG_REF); if (orgRef == null) { return null; } List<PrismReferenceValue> values = orgRef.getValues(); ValuePolicyType valuePolicy = null; List<PrismObject<OrgType>> orgs = new ArrayList<PrismObject<OrgType>>(); try { for (PrismReferenceValue orgRefValue : values) { if (orgRefValue != null) { if (valuePolicy != null) { throw new IllegalStateException( "Found more than one policy while trying to validate user's password. Please check your configuration"); } PrismObject<OrgType> org = resolver.resolve(orgRefValue, "resolving parent org ref", null, null, result); orgs.add(org); valuePolicy = resolvePolicy(org, task, result); } } } catch (ObjectNotFoundException ex) { throw new IllegalStateException(ex); } // go deeper if (valuePolicy == null) { for (PrismObject<OrgType> orgType : orgs) { valuePolicy = determineValuePolicy(orgType, task, result); if (valuePolicy != null) { return valuePolicy; } } } return valuePolicy; } private ValuePolicyType resolvePolicy(PrismObject<OrgType> org, Task task, OperationResult result) throws SchemaException { try { OrgType orgType = org.asObjectable(); ObjectReferenceType ref = orgType.getPasswordPolicyRef(); if (ref == null) { return null; } return resolver.resolve( ref, ValuePolicyType.class, null, "resolving password policy for organization", task, result); } catch (ObjectNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); throw new IllegalStateException(e); } } <F extends ObjectType> void processPasswordPolicy( LensProjectionContext projectionContext, LensContext<F> context, Task task, OperationResult result) throws SchemaException, PolicyViolationException { ObjectDelta accountDelta = projectionContext.getDelta(); if (accountDelta == null) { LOGGER.trace("Skipping processing password policies. Shadow delta not specified."); return; } if (ChangeType.DELETE == accountDelta.getChangeType()) { return; } PrismObject<ShadowType> accountShadow = null; PrismProperty<PasswordType> password = null; if (ChangeType.ADD == accountDelta.getChangeType()) { accountShadow = accountDelta.getObjectToAdd(); if (accountShadow != null) { password = accountShadow.findProperty(SchemaConstants.PATH_PASSWORD_VALUE); } } if (ChangeType.MODIFY == accountDelta.getChangeType() || password == null) { PropertyDelta<PasswordType> passwordValueDelta = null; if (accountDelta != null) { passwordValueDelta = accountDelta.findPropertyDelta(SchemaConstants.PATH_PASSWORD_VALUE); // Modification sanity check if (accountDelta.getChangeType() == ChangeType.MODIFY && passwordValueDelta != null && (passwordValueDelta.isAdd() || passwordValueDelta.isDelete())) { throw new SchemaException( "Shadow password value cannot be added or deleted, it can only be replaced"); } if (passwordValueDelta == null) { LOGGER.trace( "Skipping processing password policies. Shadow delta does not contain password change."); return; } password = (PrismProperty<PasswordType>) passwordValueDelta.getItemNewMatchingPath(null); } } // PrismProperty<PasswordType> password = getPassword(projectionContext); ValuePolicyType passwordPolicy = null; if (isCheckOrgPolicy(context)) { passwordPolicy = determineValuePolicy(context.getFocusContext().getObjectAny(), task, result); context.getFocusContext().setOrgPasswordPolicy(passwordPolicy); } else { passwordPolicy = projectionContext.getEffectivePasswordPolicy(); } processPasswordPolicy(passwordPolicy, password, result); } private <F extends ObjectType> boolean isCheckOrgPolicy(LensContext<F> context) throws SchemaException { LensFocusContext focusCtx = context.getFocusContext(); if (focusCtx.getDelta() != null) { if (focusCtx.getDelta().isAdd()) { return false; } if (focusCtx.getDelta().isModify() && focusCtx.getDelta().hasItemDelta(SchemaConstants.PATH_PASSWORD_VALUE)) { return false; } } if (focusCtx.getOrgPasswordPolicy() != null) { return false; } return true; } // On missing password this returns empty string (""). It is then up to password policy whether it // allows empty passwords or not. private String determinePasswordValue(PrismProperty<PasswordType> password) { if (password == null || password.getValue(ProtectedStringType.class) == null) { return null; } ProtectedStringType passValue = password.getValue(ProtectedStringType.class).getValue(); if (passValue == null) { return null; } String passwordStr = passValue.getClearValue(); if (passwordStr == null && passValue.getEncryptedDataType() != null) { // TODO: is this appropriate handling??? try { passwordStr = protector.decryptString(passValue); } catch (EncryptionException ex) { throw new SystemException("Failed to process password for user: ", ex); } } return passwordStr; } }
/** @author lazyman */ @PageDescriptor( url = "/admin/reports/create", action = { @AuthorizationAction( actionUri = PageAdminReports.AUTH_REPORTS_ALL, label = PageAdminConfiguration.AUTH_CONFIGURATION_ALL_LABEL, description = PageAdminConfiguration.AUTH_CONFIGURATION_ALL_DESCRIPTION), @AuthorizationAction( actionUri = AuthorizationConstants.AUTZ_UI_REPORTS_REPORT_CREATE_URL, label = "PageNewReport.auth.reports.label", description = "PageNewReport.auth.reports.description") }) public class PageNewReport extends PageAdminReports { private static final Trace LOGGER = TraceManager.getTrace(PageNewReport.class); private static final String ID_MAIN_FORM = "mainForm"; private static final String ID_BUTTON_BAR = "buttonBar"; private static final String ID_IMPORT_RADIO_GROUP = "importRadioGroup"; private static final String ID_FILE_RADIO = "fileRadio"; private static final String ID_XML_RADIO = "xmlRadio"; private static final String ID_IMPORT_FILE_BUTTON = "importFileButton"; private static final String ID_IMPORT_XML_BUTTON = "importXmlButton"; private static final String ID_INPUT = "input"; private static final String ID_INPUT_ACE = "inputAce"; private static final String ID_ACE_EDITOR = "aceEditor"; private static final String ID_INPUT_FILE_LABEL = "inputFileLabel"; private static final String ID_INPUT_FILE = "inputFile"; private static final String ID_FILE_INPUT = "fileInput"; private static final String OPERATION_IMPORT_REPORT_XML = "Import Report from XML"; private static final String OPERATION_IMPORT_REPORT = "Import Report from file"; private static final Integer INPUT_FILE = 1; private static final Integer INPUT_XML = 2; private Model<String> xmlEditorModel; public PageNewReport() { xmlEditorModel = new Model<String>(null); initLayout(); } private void initLayout() { Form mainForm = new Form(ID_MAIN_FORM); add(mainForm); final WebMarkupContainer input = new WebMarkupContainer(ID_INPUT); input.setOutputMarkupId(true); mainForm.add(input); final WebMarkupContainer buttonBar = new WebMarkupContainer(ID_BUTTON_BAR); buttonBar.setOutputMarkupId(true); mainForm.add(buttonBar); final IModel<Integer> groupModel = new Model<Integer>(INPUT_FILE); RadioGroup importRadioGroup = new RadioGroup(ID_IMPORT_RADIO_GROUP, groupModel); importRadioGroup.add( new AjaxFormChoiceComponentUpdatingBehavior() { @Override protected void onUpdate(AjaxRequestTarget target) { target.add(input); target.add(buttonBar); } }); mainForm.add(importRadioGroup); Radio fileRadio = new Radio(ID_FILE_RADIO, new Model(INPUT_FILE), importRadioGroup); importRadioGroup.add(fileRadio); Radio xmlRadio = new Radio(ID_XML_RADIO, new Model(INPUT_XML), importRadioGroup); importRadioGroup.add(xmlRadio); WebMarkupContainer inputAce = new WebMarkupContainer(ID_INPUT_ACE); addVisibileForInputType(inputAce, INPUT_XML, groupModel); input.add(inputAce); AceEditor aceEditor = new AceEditor(ID_ACE_EDITOR, xmlEditorModel); aceEditor.setOutputMarkupId(true); inputAce.add(aceEditor); WebMarkupContainer inputFileLabel = new WebMarkupContainer(ID_INPUT_FILE_LABEL); addVisibileForInputType(inputFileLabel, INPUT_FILE, groupModel); input.add(inputFileLabel); WebMarkupContainer inputFile = new WebMarkupContainer(ID_INPUT_FILE); addVisibileForInputType(inputFile, INPUT_FILE, groupModel); input.add(inputFile); FileUploadField fileInput = new FileUploadField(ID_FILE_INPUT); inputFile.add(fileInput); initButtons(buttonBar, groupModel); } private void addVisibileForInputType( Component comp, final Integer type, final IModel<Integer> groupModel) { comp.add( new VisibleEnableBehaviour() { @Override public boolean isVisible() { return type.equals(groupModel.getObject()); } }); } private void initButtons(WebMarkupContainer buttonBar, IModel<Integer> inputType) { AjaxSubmitButton saveFileButton = new AjaxSubmitButton( ID_IMPORT_FILE_BUTTON, createStringResource("PageNewReport.button.import")) { @Override protected void onSubmit(AjaxRequestTarget target, Form<?> form) { importReportFromFilePerformed(target); } @Override protected void onError(AjaxRequestTarget target, Form<?> form) { target.add(getFeedbackPanel()); } }; addVisibileForInputType(saveFileButton, INPUT_FILE, inputType); buttonBar.add(saveFileButton); AjaxSubmitButton saveXmlButton = new AjaxSubmitButton( ID_IMPORT_XML_BUTTON, createStringResource("PageNewReport.button.import")) { @Override protected void onSubmit(AjaxRequestTarget target, Form<?> form) { importReportFromStreamPerformed(target); } @Override protected void onError(AjaxRequestTarget target, Form<?> form) { target.add(getFeedbackPanel()); } }; addVisibileForInputType(saveXmlButton, INPUT_XML, inputType); buttonBar.add(saveXmlButton); } private void importReportFromFilePerformed(AjaxRequestTarget target) { OperationResult result = new OperationResult(OPERATION_IMPORT_REPORT); FileUploadField file = (FileUploadField) get(createComponentPath(ID_MAIN_FORM, ID_INPUT, ID_INPUT_FILE, ID_FILE_INPUT)); final FileUpload uploadedFile = file.getFileUpload(); if (uploadedFile == null) { error(getString("PageNewReport.message.nullFile")); target.add(getFeedbackPanel()); return; } InputStream stream = null; File newFile = null; try { // Create new file MidPointApplication application = getMidpointApplication(); WebApplicationConfiguration config = application.getWebApplicationConfiguration(); File folder = new File(config.getImportFolder()); if (!folder.exists() || !folder.isDirectory()) { folder.mkdir(); } newFile = new File(folder, uploadedFile.getClientFileName()); // Check new file, delete if it already exists if (newFile.exists()) { newFile.delete(); } // Save file // Task task = createSimpleTask(OPERATION_IMPORT_FILE); newFile.createNewFile(); uploadedFile.writeTo(newFile); InputStreamReader reader = new InputStreamReader(new FileInputStream(newFile), "utf-8"); // reader. stream = new ReaderInputStream(reader, reader.getEncoding()); byte[] reportIn = IOUtils.toByteArray(stream); setResponsePage(new PageReport(new ReportDto(Base64.encodeBase64(reportIn)))); } catch (Exception ex) { result.recordFatalError("Couldn't import file.", ex); LoggingUtils.logException(LOGGER, "Couldn't import file", ex); } finally { if (stream != null) { IOUtils.closeQuietly(stream); } if (newFile != null) { FileUtils.deleteQuietly(newFile); } } showResult(result); target.add(getFeedbackPanel()); } private void importReportFromStreamPerformed(AjaxRequestTarget target) { String xml = xmlEditorModel.getObject(); if (StringUtils.isEmpty(xml)) { error(getString("PageNewReport.message.emptyXml")); target.add(getFeedbackPanel()); return; } OperationResult result = new OperationResult(OPERATION_IMPORT_REPORT_XML); InputStream stream = null; try { setResponsePage(new PageReport(new ReportDto(Base64.encodeBase64(xml.getBytes())))); } catch (Exception ex) { result.recordFatalError("Couldn't import object.", ex); LoggingUtils.logException(LOGGER, "Error occured during xml import", ex); } finally { if (stream != null) { IOUtils.closeQuietly(stream); } } if (result.isSuccess()) { xmlEditorModel.setObject(null); } showResult(result); target.add(getFeedbackPanel()); } }
/** @author semancik */ public class IcfConfigurationTransformer { private static final Trace LOGGER = TraceManager.getTrace(IcfConfigurationTransformer.class); private ConnectorType connectorType; private ConnectorInfo cinfo; private Protector protector; public IcfConfigurationTransformer( ConnectorType connectorType, ConnectorInfo cinfo, Protector protector) { super(); this.connectorType = connectorType; this.cinfo = cinfo; this.protector = protector; } /** * Transforms midPoint XML configuration of the connector to the ICF configuration. * * <p>The "configuration" part of the XML resource definition will be used. * * <p>The provided ICF APIConfiguration will be modified, some values may be overwritten. * * @param apiConfig ICF connector configuration * @param resourceType midPoint XML configuration * @throws SchemaException * @throws ConfigurationException */ public APIConfiguration transformConnectorConfiguration(PrismContainerValue configuration) throws SchemaException, ConfigurationException { APIConfiguration apiConfig = cinfo.createDefaultAPIConfiguration(); ConfigurationProperties configProps = apiConfig.getConfigurationProperties(); // The namespace of all the configuration properties specific to the // connector instance will have a connector instance namespace. This // namespace can be found in the resource definition. String connectorConfNs = connectorType.getNamespace(); PrismContainer configurationPropertiesContainer = configuration.findContainer( ConnectorFactoryIcfImpl.CONNECTOR_SCHEMA_CONFIGURATION_PROPERTIES_ELEMENT_QNAME); if (configurationPropertiesContainer == null) { // Also try this. This is an older way. configurationPropertiesContainer = configuration.findContainer( new QName( connectorConfNs, ConnectorFactoryIcfImpl .CONNECTOR_SCHEMA_CONFIGURATION_PROPERTIES_ELEMENT_LOCAL_NAME)); } transformConnectorConfiguration(configProps, configurationPropertiesContainer, connectorConfNs); PrismContainer connectorPoolContainer = configuration.findContainer( new QName( ConnectorFactoryIcfImpl.NS_ICF_CONFIGURATION, ConnectorFactoryIcfImpl .CONNECTOR_SCHEMA_CONNECTOR_POOL_CONFIGURATION_XML_ELEMENT_NAME)); ObjectPoolConfiguration connectorPoolConfiguration = apiConfig.getConnectorPoolConfiguration(); transformConnectorPoolConfiguration(connectorPoolConfiguration, connectorPoolContainer); PrismProperty producerBufferSizeProperty = configuration.findProperty( new QName( ConnectorFactoryIcfImpl.NS_ICF_CONFIGURATION, ConnectorFactoryIcfImpl.CONNECTOR_SCHEMA_PRODUCER_BUFFER_SIZE_XML_ELEMENT_NAME)); if (producerBufferSizeProperty != null) { apiConfig.setProducerBufferSize(parseInt(producerBufferSizeProperty)); } PrismContainer connectorTimeoutsContainer = configuration.findContainer( new QName( ConnectorFactoryIcfImpl.NS_ICF_CONFIGURATION, ConnectorFactoryIcfImpl.CONNECTOR_SCHEMA_TIMEOUTS_XML_ELEMENT_NAME)); transformConnectorTimeoutsConfiguration(apiConfig, connectorTimeoutsContainer); PrismContainer resultsHandlerConfigurationContainer = configuration.findContainer( new QName( ConnectorFactoryIcfImpl.NS_ICF_CONFIGURATION, ConnectorFactoryIcfImpl .CONNECTOR_SCHEMA_RESULTS_HANDLER_CONFIGURATION_ELEMENT_LOCAL_NAME)); ResultsHandlerConfiguration resultsHandlerConfiguration = apiConfig.getResultsHandlerConfiguration(); transformResultsHandlerConfiguration( resultsHandlerConfiguration, resultsHandlerConfigurationContainer); return apiConfig; } private void transformConnectorConfiguration( ConfigurationProperties configProps, PrismContainer<?> configurationPropertiesContainer, String connectorConfNs) throws ConfigurationException, SchemaException { if (configurationPropertiesContainer == null || configurationPropertiesContainer.getValue() == null) { throw new SchemaException("No configuration properties container in " + connectorType); } int numConfingProperties = 0; List<QName> wrongNamespaceProperties = new ArrayList<>(); for (PrismProperty prismProperty : configurationPropertiesContainer.getValue().getProperties()) { QName propertyQName = prismProperty.getElementName(); // All the elements must be in a connector instance // namespace. if (propertyQName.getNamespaceURI() == null || !propertyQName.getNamespaceURI().equals(connectorConfNs)) { LOGGER.warn( "Found element with a wrong namespace ({}) in {}", propertyQName.getNamespaceURI(), connectorType); wrongNamespaceProperties.add(propertyQName); } else { numConfingProperties++; // Local name of the element is the same as the name // of ICF configuration property String propertyName = propertyQName.getLocalPart(); ConfigurationProperty property = configProps.getProperty(propertyName); if (property == null) { throw new ConfigurationException("Unknown configuration property " + propertyName); } // Check (java) type of ICF configuration property, // behave accordingly Class<?> type = property.getType(); if (type.isArray()) { property.setValue(convertToIcfArray(prismProperty, type.getComponentType())); // property.setValue(prismProperty.getRealValuesArray(type.getComponentType())); } else { // Single-valued property are easy to convert property.setValue(convertToIcfSingle(prismProperty, type)); // property.setValue(prismProperty.getRealValue(type)); } } } // empty configuration is OK e.g. when creating a new resource using wizard if (numConfingProperties == 0 && !wrongNamespaceProperties.isEmpty()) { throw new SchemaException( "No configuration properties found. Wrong namespace? (expected: " + connectorConfNs + ", present e.g. " + wrongNamespaceProperties.get(0) + ")"); } } private void transformConnectorPoolConfiguration( ObjectPoolConfiguration connectorPoolConfiguration, PrismContainer<?> connectorPoolContainer) throws SchemaException { if (connectorPoolContainer == null || connectorPoolContainer.getValue() == null) { return; } for (PrismProperty prismProperty : connectorPoolContainer.getValue().getProperties()) { QName propertyQName = prismProperty.getElementName(); if (propertyQName.getNamespaceURI().equals(ConnectorFactoryIcfImpl.NS_ICF_CONFIGURATION)) { String subelementName = propertyQName.getLocalPart(); if (ConnectorFactoryIcfImpl .CONNECTOR_SCHEMA_CONNECTOR_POOL_CONFIGURATION_MIN_EVICTABLE_IDLE_TIME_MILLIS.equals( subelementName)) { connectorPoolConfiguration.setMinEvictableIdleTimeMillis(parseLong(prismProperty)); } else if (ConnectorFactoryIcfImpl.CONNECTOR_SCHEMA_CONNECTOR_POOL_CONFIGURATION_MIN_IDLE .equals(subelementName)) { connectorPoolConfiguration.setMinIdle(parseInt(prismProperty)); } else if (ConnectorFactoryIcfImpl.CONNECTOR_SCHEMA_CONNECTOR_POOL_CONFIGURATION_MAX_IDLE .equals(subelementName)) { connectorPoolConfiguration.setMaxIdle(parseInt(prismProperty)); } else if (ConnectorFactoryIcfImpl.CONNECTOR_SCHEMA_CONNECTOR_POOL_CONFIGURATION_MAX_OBJECTS .equals(subelementName)) { connectorPoolConfiguration.setMaxObjects(parseInt(prismProperty)); } else if (ConnectorFactoryIcfImpl.CONNECTOR_SCHEMA_CONNECTOR_POOL_CONFIGURATION_MAX_WAIT .equals(subelementName)) { connectorPoolConfiguration.setMaxWait(parseLong(prismProperty)); } else { throw new SchemaException( "Unexpected element " + propertyQName + " in " + ConnectorFactoryIcfImpl .CONNECTOR_SCHEMA_CONNECTOR_POOL_CONFIGURATION_XML_ELEMENT_NAME); } } else { throw new SchemaException( "Unexpected element " + propertyQName + " in " + ConnectorFactoryIcfImpl .CONNECTOR_SCHEMA_CONNECTOR_POOL_CONFIGURATION_XML_ELEMENT_NAME); } } } private void transformConnectorTimeoutsConfiguration( APIConfiguration apiConfig, PrismContainer<?> connectorTimeoutsContainer) throws SchemaException { if (connectorTimeoutsContainer == null || connectorTimeoutsContainer.getValue() == null) { return; } for (PrismProperty prismProperty : connectorTimeoutsContainer.getValue().getProperties()) { QName propertQName = prismProperty.getElementName(); if (ConnectorFactoryIcfImpl.NS_ICF_CONFIGURATION.equals(propertQName.getNamespaceURI())) { String opName = propertQName.getLocalPart(); Class<? extends APIOperation> apiOpClass = ConnectorFactoryIcfImpl.resolveApiOpClass(opName); if (apiOpClass != null) { apiConfig.setTimeout(apiOpClass, parseInt(prismProperty)); } else { throw new SchemaException( "Unknown operation name " + opName + " in " + ConnectorFactoryIcfImpl.CONNECTOR_SCHEMA_TIMEOUTS_XML_ELEMENT_NAME); } } } } private void transformResultsHandlerConfiguration( ResultsHandlerConfiguration resultsHandlerConfiguration, PrismContainer<?> resultsHandlerConfigurationContainer) throws SchemaException { if (resultsHandlerConfigurationContainer == null || resultsHandlerConfigurationContainer.getValue() == null) { return; } for (PrismProperty prismProperty : resultsHandlerConfigurationContainer.getValue().getProperties()) { QName propertyQName = prismProperty.getElementName(); if (propertyQName.getNamespaceURI().equals(ConnectorFactoryIcfImpl.NS_ICF_CONFIGURATION)) { String subelementName = propertyQName.getLocalPart(); if (ConnectorFactoryIcfImpl .CONNECTOR_SCHEMA_RESULTS_HANDLER_CONFIGURATION_ENABLE_NORMALIZING_RESULTS_HANDLER .equals(subelementName)) { resultsHandlerConfiguration.setEnableNormalizingResultsHandler( parseBoolean(prismProperty)); } else if (ConnectorFactoryIcfImpl .CONNECTOR_SCHEMA_RESULTS_HANDLER_CONFIGURATION_ENABLE_FILTERED_RESULTS_HANDLER.equals( subelementName)) { resultsHandlerConfiguration.setEnableFilteredResultsHandler(parseBoolean(prismProperty)); } else if (ConnectorFactoryIcfImpl .CONNECTOR_SCHEMA_RESULTS_HANDLER_CONFIGURATION_FILTERED_RESULTS_HANDLER_IN_VALIDATION_MODE .equals(subelementName)) { resultsHandlerConfiguration.setFilteredResultsHandlerInValidationMode( parseBoolean(prismProperty)); } else if (ConnectorFactoryIcfImpl .CONNECTOR_SCHEMA_RESULTS_HANDLER_CONFIGURATION_ENABLE_CASE_INSENSITIVE_HANDLER.equals( subelementName)) { resultsHandlerConfiguration.setEnableCaseInsensitiveFilter(parseBoolean(prismProperty)); } else if (ConnectorFactoryIcfImpl .CONNECTOR_SCHEMA_RESULTS_HANDLER_CONFIGURATION_ENABLE_ATTRIBUTES_TO_GET_SEARCH_RESULTS_HANDLER .equals(subelementName)) { resultsHandlerConfiguration.setEnableAttributesToGetSearchResultsHandler( parseBoolean(prismProperty)); } else { throw new SchemaException( "Unexpected element " + propertyQName + " in " + ConnectorFactoryIcfImpl .CONNECTOR_SCHEMA_RESULTS_HANDLER_CONFIGURATION_ELEMENT_LOCAL_NAME); } } else { throw new SchemaException( "Unexpected element " + propertyQName + " in " + ConnectorFactoryIcfImpl .CONNECTOR_SCHEMA_RESULTS_HANDLER_CONFIGURATION_ELEMENT_LOCAL_NAME); } } } private int parseInt(PrismProperty<?> prop) { return prop.getRealValue(Integer.class); } private long parseLong(PrismProperty<?> prop) { Object realValue = prop.getRealValue(); if (realValue instanceof Long) { return (Long) realValue; } else if (realValue instanceof Integer) { return ((Integer) realValue); } else { throw new IllegalArgumentException("Cannot convert " + realValue.getClass() + " to long"); } } private boolean parseBoolean(PrismProperty<?> prop) { return prop.getRealValue(Boolean.class); } private Object convertToIcfSingle(PrismProperty<?> configProperty, Class<?> expectedType) throws ConfigurationException { if (configProperty == null) { return null; } PrismPropertyValue<?> pval = configProperty.getValue(); return convertToIcf(pval, expectedType); } private Object[] convertToIcfArray(PrismProperty prismProperty, Class<?> componentType) throws ConfigurationException { List<PrismPropertyValue> values = prismProperty.getValues(); Object valuesArrary = Array.newInstance(componentType, values.size()); for (int j = 0; j < values.size(); ++j) { Object icfValue = convertToIcf(values.get(j), componentType); Array.set(valuesArrary, j, icfValue); } return (Object[]) valuesArrary; } private Object convertToIcf(PrismPropertyValue<?> pval, Class<?> expectedType) throws ConfigurationException { Object midPointRealValue = pval.getValue(); if (expectedType.equals(GuardedString.class)) { // Guarded string is a special ICF beast // The value must be ProtectedStringType if (midPointRealValue instanceof ProtectedStringType) { ProtectedStringType ps = (ProtectedStringType) pval.getValue(); return IcfUtil.toGuardedString( ps, pval.getParent().getElementName().getLocalPart(), protector); } else { throw new ConfigurationException( "Expected protected string as value of configuration property " + pval.getParent().getElementName().getLocalPart() + " but got " + midPointRealValue.getClass()); } } else if (expectedType.equals(GuardedByteArray.class)) { // Guarded string is a special ICF beast // TODO // return new GuardedByteArray(Base64.decodeBase64((ProtectedByteArrayType) // pval.getValue())); return new GuardedByteArray(((ProtectedByteArrayType) pval.getValue()).getClearBytes()); } else if (midPointRealValue instanceof PolyString) { return ((PolyString) midPointRealValue).getOrig(); } else if (midPointRealValue instanceof PolyStringType) { return ((PolyStringType) midPointRealValue).getOrig(); } else if (expectedType.equals(File.class) && midPointRealValue instanceof String) { return new File((String) midPointRealValue); } else if (expectedType.equals(String.class) && midPointRealValue instanceof ProtectedStringType) { try { return protector.decryptString((ProtectedStringType) midPointRealValue); } catch (EncryptionException e) { throw new ConfigurationException(e); } } else { return midPointRealValue; } } }
/** * Test UCF implementation with OpenDJ and ICF LDAP connector. * * <p>This test is using embedded OpenDJ as a resource and ICF LDAP connector. The test is executed * by direct calls to the UCF interface. * * @author Radovan Semancik * @author Katka Valalikova * <p>This is an UCF test. It shold not need repository or other things from the midPoint spring * context except from the provisioning beans. But due to a general issue with spring context * initialization this is a lesser evil for now (MID-392) */ @ContextConfiguration(locations = {"classpath:ctx-provisioning-test-no-repo.xml"}) public class TestUcfOpenDj extends AbstractTestNGSpringContextTests { private static final String FILENAME_RESOURCE_OPENDJ = "src/test/resources/object/resource-opendj.xml"; private static final String FILENAME_RESOURCE_OPENDJ_BAD = "src/test/resources/object/resource-opendj-bad.xml"; private static final String FILENAME_CONNECTOR_LDAP = "src/test/resources/ucf/connector-ldap.xml"; private ResourceType resourceType; private ResourceType badResourceType; private ConnectorType connectorType; private ConnectorFactory factory; private ConnectorInstance cc; private PrismSchema connectorSchema; private ResourceSchema resourceSchema; private static Trace LOGGER = TraceManager.getTrace(TestUcfOpenDj.class); @Autowired(required = true) ConnectorFactory connectorFactoryIcfImpl; @Autowired(required = true) Protector protector; @Autowired(required = true) PrismContext prismContext; protected static OpenDJController openDJController = new OpenDJController(); public TestUcfOpenDj() throws JAXBException { System.setProperty("midpoint.home", "target/midPointHome/"); } @BeforeSuite public void setup() throws SchemaException, SAXException, IOException { PrettyPrinter.setDefaultNamespacePrefix(MidPointConstants.NS_MIDPOINT_PUBLIC_PREFIX); PrismTestUtil.resetPrismContext(MidPointPrismContextFactory.FACTORY); } @BeforeClass public static void startLdap() throws Exception { LOGGER.info("------------------------------------------------------------------------------"); LOGGER.info("START: OpenDjUcfTest"); LOGGER.info("------------------------------------------------------------------------------"); openDJController.startCleanServer(); } @AfterClass public static void stopLdap() throws Exception { openDJController.stop(); LOGGER.info("------------------------------------------------------------------------------"); LOGGER.info("STOP: OpenDjUcfTest"); LOGGER.info("------------------------------------------------------------------------------"); } @BeforeMethod public void initUcf() throws Exception { TestUtil.displayTestTile("initUcf"); File file = new File(FILENAME_RESOURCE_OPENDJ); FileInputStream fis = new FileInputStream(file); // Resource PrismObject<ResourceType> resource = PrismTestUtil.parseObject(new File(FILENAME_RESOURCE_OPENDJ)); resourceType = resource.asObjectable(); // Resource: Second copy for negative test cases PrismObject<ResourceType> badResource = PrismTestUtil.parseObject(new File(FILENAME_RESOURCE_OPENDJ_BAD)); badResourceType = badResource.asObjectable(); // Connector PrismObject<ConnectorType> connector = PrismTestUtil.parseObject(new File(FILENAME_CONNECTOR_LDAP)); connectorType = connector.asObjectable(); factory = connectorFactoryIcfImpl; cc = factory.createConnectorInstance( connectorType, ResourceTypeUtil.getResourceNamespace(resourceType), "test connector"); AssertJUnit.assertNotNull("Cannot create connector instance", cc); connectorSchema = cc.generateConnectorSchema(); AssertJUnit.assertNotNull("Cannot generate connector schema", cc); display("Connector schema", connectorSchema); OperationResult result = new OperationResult("initUcf"); cc.configure(resourceType.getConnectorConfiguration().asPrismContainerValue(), result); cc.initialize(null, null, false, result); // TODO: assert something resourceSchema = cc.fetchResourceSchema(null, result); display("Resource schema", resourceSchema); AssertJUnit.assertNotNull(resourceSchema); } @AfterMethod public void shutdownUcf() throws Exception {} @Test public void test010ConnectorSchemaSanity() throws Exception { final String TEST_NAME = "test010ConnectorSchemaSanity"; TestUtil.displayTestTile(TEST_NAME); ProvisioningTestUtil.assertConnectorSchemaSanity(connectorSchema, "LDAP connector"); } @Test public void test020ResourceSchemaSanity() throws Exception { final String TEST_NAME = "test020ResourceSchemaSanity"; TestUtil.displayTestTile(TEST_NAME); QName objectClassQname = new QName( ResourceTypeUtil.getResourceNamespace(resourceType), ProvisioningTestUtil.OBJECT_CLASS_INETORGPERSON_NAME); ObjectClassComplexTypeDefinition accountDefinition = resourceSchema.findObjectClassDefinition(objectClassQname); assertNotNull("No object class definition " + objectClassQname, accountDefinition); // assertEquals("Object class " + objectClassQname + " is not account", ShadowKindType.ACCOUNT, // accountDefinition.getKind()); // assertTrue("Object class " + objectClassQname + " is not default account", // accountDefinition.isDefaultInAKind()); assertFalse("Object class " + objectClassQname + " is empty", accountDefinition.isEmpty()); assertFalse("Object class " + objectClassQname + " is empty", accountDefinition.isIgnored()); Collection<? extends ResourceAttributeDefinition> identifiers = accountDefinition.getIdentifiers(); assertNotNull("Null identifiers for " + objectClassQname, identifiers); assertFalse("Empty identifiers for " + objectClassQname, identifiers.isEmpty()); ResourceAttributeDefinition<String> idPrimaryDef = accountDefinition.findAttributeDefinition( new QName( ResourceTypeUtil.getResourceNamespace(resourceType), ProvisioningTestUtil.RESOURCE_OPENDJ_PRIMARY_IDENTIFIER_LOCAL_NAME)); assertNotNull( "No definition for attribute " + ProvisioningTestUtil.RESOURCE_OPENDJ_PRIMARY_IDENTIFIER_LOCAL_NAME, idPrimaryDef); assertTrue( "Attribute " + ProvisioningTestUtil.RESOURCE_OPENDJ_PRIMARY_IDENTIFIER_LOCAL_NAME + " in not an identifier", idPrimaryDef.isIdentifier(accountDefinition)); assertTrue( "Attribute " + ProvisioningTestUtil.RESOURCE_OPENDJ_PRIMARY_IDENTIFIER_LOCAL_NAME + " in not in identifiers list", identifiers.contains(idPrimaryDef)); assertEquals( "Attribute " + ProvisioningTestUtil.RESOURCE_OPENDJ_PRIMARY_IDENTIFIER_LOCAL_NAME + " has wrong native name", ProvisioningTestUtil.RESOURCE_OPENDJ_PRIMARY_IDENTIFIER_LOCAL_NAME, idPrimaryDef.getNativeAttributeName()); assertEquals( "Attribute " + ProvisioningTestUtil.RESOURCE_OPENDJ_PRIMARY_IDENTIFIER_LOCAL_NAME + " has wrong framework name", Uid.NAME, idPrimaryDef.getFrameworkAttributeName()); ResourceAttributeDefinition<String> idSecondaryDef = accountDefinition.findAttributeDefinition( new QName( ResourceTypeUtil.getResourceNamespace(resourceType), ProvisioningTestUtil.RESOURCE_OPENDJ_SECONDARY_IDENTIFIER_LOCAL_NAME)); assertNotNull( "No definition for attribute " + ConnectorFactoryIcfImpl.ICFS_NAME, idSecondaryDef); assertTrue( "Attribute " + ProvisioningTestUtil.RESOURCE_OPENDJ_SECONDARY_IDENTIFIER_LOCAL_NAME + " in not secondary identifier", idSecondaryDef.isSecondaryIdentifier(accountDefinition)); assertFalse( "Attribute " + ProvisioningTestUtil.RESOURCE_OPENDJ_SECONDARY_IDENTIFIER_LOCAL_NAME + " in in identifiers list and it should NOT be", identifiers.contains(idSecondaryDef)); assertTrue( "Attribute " + ProvisioningTestUtil.RESOURCE_OPENDJ_SECONDARY_IDENTIFIER_LOCAL_NAME + " in not in secomdary identifiers list", accountDefinition.getSecondaryIdentifiers().contains(idSecondaryDef)); assertEquals( "Attribute " + ProvisioningTestUtil.RESOURCE_OPENDJ_SECONDARY_IDENTIFIER_LOCAL_NAME + " has wrong native name", ProvisioningTestUtil.RESOURCE_OPENDJ_SECONDARY_IDENTIFIER_LOCAL_NAME, idSecondaryDef.getNativeAttributeName()); assertEquals( "Attribute " + ProvisioningTestUtil.RESOURCE_OPENDJ_SECONDARY_IDENTIFIER_LOCAL_NAME + " has wrong framework name", Name.NAME, idSecondaryDef.getFrameworkAttributeName()); assertEquals("Unexpected identifiers: " + identifiers, 1, identifiers.size()); assertEquals( "Unexpected secondary identifiers: " + accountDefinition.getSecondaryIdentifiers(), 1, accountDefinition.getSecondaryIdentifiers().size()); } private Collection<ResourceAttribute<?>> addSampleResourceObject( String name, String givenName, String familyName) throws CommunicationException, GenericFrameworkException, SchemaException, ObjectAlreadyExistsException, ConfigurationException { OperationResult result = new OperationResult(this.getClass().getName() + ".testAdd"); QName objectClassQname = new QName( ResourceTypeUtil.getResourceNamespace(resourceType), ProvisioningTestUtil.OBJECT_CLASS_INETORGPERSON_NAME); ObjectClassComplexTypeDefinition accountDefinition = resourceSchema.findObjectClassDefinition(objectClassQname); assertNotNull("No object class definition " + objectClassQname, accountDefinition); ResourceAttributeContainer resourceObject = accountDefinition.instantiate(ShadowType.F_ATTRIBUTES); ResourceAttributeDefinition<String> attributeDefinition = accountDefinition.findAttributeDefinition( new QName( ResourceTypeUtil.getResourceNamespace(resourceType), ProvisioningTestUtil.RESOURCE_OPENDJ_SECONDARY_IDENTIFIER_LOCAL_NAME)); ResourceAttribute<String> attribute = attributeDefinition.instantiate(); attribute.setValue( new PrismPropertyValue<String>("uid=" + name + ",ou=people,dc=example,dc=com")); resourceObject.add(attribute); attributeDefinition = accountDefinition.findAttributeDefinition( new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "sn")); attribute = attributeDefinition.instantiate(); attribute.setValue(new PrismPropertyValue(familyName)); resourceObject.add(attribute); attributeDefinition = accountDefinition.findAttributeDefinition( new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "cn")); attribute = attributeDefinition.instantiate(); attribute.setValue(new PrismPropertyValue(givenName + " " + familyName)); resourceObject.add(attribute); attributeDefinition = accountDefinition.findAttributeDefinition( new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "givenName")); attribute = attributeDefinition.instantiate(); attribute.setValue(new PrismPropertyValue(givenName)); resourceObject.add(attribute); PrismObject<ShadowType> shadow = wrapInShadow(ShadowType.class, resourceObject); Set<Operation> operation = new HashSet<Operation>(); Collection<ResourceAttribute<?>> resourceAttributes = cc.addObject(shadow, operation, result); return resourceAttributes; } private String getEntryUuid(Collection<ResourceAttribute<?>> identifiers) { for (ResourceAttribute<?> identifier : identifiers) { if (identifier .getElementName() .equals( new QName( ResourceTypeUtil.getResourceNamespace(resourceType), ProvisioningTestUtil.RESOURCE_OPENDJ_PRIMARY_IDENTIFIER_LOCAL_NAME))) { return identifier.getValue(String.class).getValue(); } } return null; } @Test public void test100AddDeleteObject() throws Exception { final String TEST_NAME = "test100AddDeleteObject"; TestUtil.displayTestTile(this, TEST_NAME); OperationResult result = new OperationResult(this.getClass().getName() + "." + TEST_NAME); Collection<ResourceAttribute<?>> identifiers = addSampleResourceObject("john", "John", "Smith"); String uid = null; for (ResourceAttribute<?> resourceAttribute : identifiers) { if (ConnectorFactoryIcfImpl.ICFS_UID.equals(resourceAttribute.getElementName())) { uid = resourceAttribute.getValue(String.class).getValue(); System.out.println("uuuuid:" + uid); assertNotNull(uid); } } ObjectClassComplexTypeDefinition accountDefinition = resourceSchema.findObjectClassDefinition( ProvisioningTestUtil.OBJECT_CLASS_INETORGPERSON_NAME); cc.deleteObject(accountDefinition, null, identifiers, result); ResourceObjectIdentification identification = new ResourceObjectIdentification(accountDefinition, identifiers); PrismObject<ShadowType> resObj = null; try { resObj = cc.fetchObject(ShadowType.class, identification, null, result); Assert.fail(); } catch (ObjectNotFoundException ex) { AssertJUnit.assertNull(resObj); } } @Test public void test110ChangeModifyObject() throws Exception { final String TEST_NAME = "test110ChangeModifyObject"; TestUtil.displayTestTile(this, TEST_NAME); OperationResult result = new OperationResult(this.getClass().getName() + "." + TEST_NAME); Collection<ResourceAttribute<?>> identifiers = addSampleResourceObject("john", "John", "Smith"); Set<Operation> changes = new HashSet<Operation>(); changes.add(createAddAttributeChange("employeeNumber", "123123123")); changes.add(createReplaceAttributeChange("sn", "Smith007")); changes.add(createAddAttributeChange("street", "Wall Street")); changes.add(createDeleteAttributeChange("givenName", "John")); ObjectClassComplexTypeDefinition accountDefinition = resourceSchema.findObjectClassDefinition( ProvisioningTestUtil.OBJECT_CLASS_INETORGPERSON_NAME); cc.modifyObject(accountDefinition, identifiers, changes, result); ResourceObjectIdentification identification = new ResourceObjectIdentification(accountDefinition, identifiers); PrismObject<ShadowType> shadow = cc.fetchObject(ShadowType.class, identification, null, result); ResourceAttributeContainer resObj = ShadowUtil.getAttributesContainer(shadow); AssertJUnit.assertNull( resObj.findAttribute( new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "givenName"))); String addedEmployeeNumber = resObj .findAttribute( new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "employeeNumber")) .getValue(String.class) .getValue(); String changedSn = resObj .findAttribute(new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "sn")) .getValues(String.class) .iterator() .next() .getValue(); String addedStreet = resObj .findAttribute(new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "street")) .getValues(String.class) .iterator() .next() .getValue(); System.out.println("changed employee number: " + addedEmployeeNumber); System.out.println("changed sn: " + changedSn); System.out.println("added street: " + addedStreet); AssertJUnit.assertEquals("123123123", addedEmployeeNumber); AssertJUnit.assertEquals("Smith007", changedSn); AssertJUnit.assertEquals("Wall Street", addedStreet); } @Test public void test200FetchChanges() throws Exception { final String TEST_NAME = "test200FetchChanges"; TestUtil.displayTestTile(this, TEST_NAME); OperationResult result = new OperationResult(this.getClass().getName() + "." + TEST_NAME); ObjectClassComplexTypeDefinition accountDefinition = resourceSchema.findObjectClassDefinition( ProvisioningTestUtil.OBJECT_CLASS_INETORGPERSON_NAME); PrismProperty<Integer> lastToken = cc.fetchCurrentToken(accountDefinition, result); System.out.println("Property:"); System.out.println(SchemaDebugUtil.prettyPrint(lastToken)); System.out.println("token " + lastToken.toString()); assertNotNull("No last token", lastToken); assertNotNull("No last token value", lastToken.getRealValue()); List<Change<ShadowType>> changes = cc.fetchChanges(accountDefinition, lastToken, null, result); AssertJUnit.assertEquals(0, changes.size()); } private PrismProperty createProperty(String propertyName, String propertyValue) { ObjectClassComplexTypeDefinition accountDefinition = resourceSchema.findObjectClassDefinition( new QName( ResourceTypeUtil.getResourceNamespace(resourceType), ProvisioningTestUtil.OBJECT_CLASS_INETORGPERSON_NAME)); ResourceAttributeDefinition propertyDef = accountDefinition.findAttributeDefinition( new QName(ResourceTypeUtil.getResourceNamespace(resourceType), propertyName)); ResourceAttribute property = propertyDef.instantiate(); property.setValue(new PrismPropertyValue(propertyValue)); return property; } private PropertyModificationOperation createReplaceAttributeChange( String propertyName, String propertyValue) { PrismProperty property = createProperty(propertyName, propertyValue); ItemPath propertyPath = new ItemPath( ShadowType.F_ATTRIBUTES, new QName(ResourceTypeUtil.getResourceNamespace(resourceType), propertyName)); PropertyDelta delta = new PropertyDelta(propertyPath, property.getDefinition(), prismContext); delta.setValueToReplace(new PrismPropertyValue(propertyValue)); PropertyModificationOperation attributeModification = new PropertyModificationOperation(delta); return attributeModification; } private PropertyModificationOperation createAddAttributeChange( String propertyName, String propertyValue) { PrismProperty property = createProperty(propertyName, propertyValue); ItemPath propertyPath = new ItemPath( ShadowType.F_ATTRIBUTES, new QName(ResourceTypeUtil.getResourceNamespace(resourceType), propertyName)); PropertyDelta delta = new PropertyDelta(propertyPath, property.getDefinition(), prismContext); delta.addValueToAdd(new PrismPropertyValue(propertyValue)); PropertyModificationOperation attributeModification = new PropertyModificationOperation(delta); return attributeModification; } private PropertyModificationOperation createDeleteAttributeChange( String propertyName, String propertyValue) { PrismProperty property = createProperty(propertyName, propertyValue); ItemPath propertyPath = new ItemPath( ShadowType.F_ATTRIBUTES, new QName(ResourceTypeUtil.getResourceNamespace(resourceType), propertyName)); PropertyDelta delta = new PropertyDelta(propertyPath, property.getDefinition(), prismContext); delta.addValueToDelete(new PrismPropertyValue(propertyValue)); PropertyModificationOperation attributeModification = new PropertyModificationOperation(delta); return attributeModification; } private PropertyModificationOperation createActivationChange(ActivationStatusType status) { PrismObjectDefinition<ShadowType> shadowDefinition = getShadowDefinition(ShadowType.class); PropertyDelta<ActivationStatusType> delta = PropertyDelta.createDelta( new ItemPath(ShadowType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS), shadowDefinition); delta.setValueToReplace(new PrismPropertyValue<ActivationStatusType>(status)); return new PropertyModificationOperation(delta); } /** * Simple call to connector test() method. * * @throws Exception */ @Test public void test300TestConnection() throws Exception { final String TEST_NAME = "test300TestConnection"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN OperationResult result = new OperationResult(TEST_NAME); // WHEN cc.test(result); // THEN result.computeStatus("test failed"); AssertJUnit.assertNotNull(result); OperationResult connectorConnectionResult = result.getSubresults().get(0); AssertJUnit.assertNotNull(connectorConnectionResult); System.out.println("Test \"connector connection\" result: " + connectorConnectionResult); AssertJUnit.assertTrue(connectorConnectionResult.isSuccess()); AssertJUnit.assertTrue(result.isSuccess()); } /** * Simple call to connector test() method. * * @throws Exception */ @Test public void test310TestConnectionNegative() throws Exception { final String TEST_NAME = "test310TestConnectionNegative"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN OperationResult result = new OperationResult(TEST_NAME); ConnectorInstance badConnector = factory.createConnectorInstance( connectorType, ResourceTypeUtil.getResourceNamespace(badResourceType), "test connector"); badConnector.configure( badResourceType.getConnectorConfiguration().asPrismContainerValue(), result); // WHEN badConnector.test(result); // THEN result.computeStatus("test failed"); display("Test result (FAILURE EXPECTED)", result); AssertJUnit.assertNotNull(result); OperationResult connectorConnectionResult = result.getSubresults().get(1); AssertJUnit.assertNotNull(connectorConnectionResult); System.out.println( "Test \"connector connection\" result: " + connectorConnectionResult + " (FAILURE EXPECTED)"); AssertJUnit.assertTrue( "Unexpected success of bad connector test", !connectorConnectionResult.isSuccess()); AssertJUnit.assertTrue(!result.isSuccess()); } /** * Test fetching and translating resource schema. * * @throws Exception */ @Test public void test400FetchResourceSchema() throws Exception { final String TEST_NAME = "test400FetchResourceSchema"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN // WHEN // The schema was fetched during test init. Now just check if it was OK. // THEN AssertJUnit.assertNotNull(resourceSchema); System.out.println(resourceSchema.debugDump()); Document xsdSchema = resourceSchema.serializeToXsd(); System.out.println( "-------------------------------------------------------------------------------------"); System.out.println(DOMUtil.printDom(xsdSchema)); System.out.println( "-------------------------------------------------------------------------------------"); ObjectClassComplexTypeDefinition accountDefinition = resourceSchema.findObjectClassDefinition( new QName( ResourceTypeUtil.getResourceNamespace(resourceType), ProvisioningTestUtil.OBJECT_CLASS_INETORGPERSON_NAME)); AssertJUnit.assertNotNull(accountDefinition); AssertJUnit.assertFalse( "No identifiers for account object class ", accountDefinition.getIdentifiers().isEmpty()); PrismPropertyDefinition uidDefinition = accountDefinition.findAttributeDefinition( new QName( ResourceTypeUtil.getResourceNamespace(resourceType), ProvisioningTestUtil.RESOURCE_OPENDJ_PRIMARY_IDENTIFIER_LOCAL_NAME)); AssertJUnit.assertNotNull(uidDefinition); for (Definition def : resourceSchema.getDefinitions()) { if (def instanceof ResourceAttributeContainerDefinition) { ResourceAttributeContainerDefinition rdef = (ResourceAttributeContainerDefinition) def; assertNotEmpty("No type name in object class", rdef.getTypeName()); assertNotEmpty( "No native object class for " + rdef.getTypeName(), rdef.getNativeObjectClass()); // This is maybe not that important, but just for a sake of // completeness assertNotEmpty("No name for " + rdef.getTypeName(), rdef.getName()); } } } @Test public void test410Capabilities() throws Exception { final String TEST_NAME = "test410Capabilities"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN OperationResult result = new OperationResult(TEST_NAME); // WHEN Collection<Object> capabilities = cc.fetchCapabilities(result); // THEN result.computeStatus("getCapabilities failed"); TestUtil.assertSuccess("getCapabilities failed (result)", result); assertFalse("Empty capabilities returned", capabilities.isEmpty()); CredentialsCapabilityType capCred = CapabilityUtil.getCapability(capabilities, CredentialsCapabilityType.class); assertNotNull("password capability not present", capCred.getPassword()); PagedSearchCapabilityType capPage = CapabilityUtil.getCapability(capabilities, PagedSearchCapabilityType.class); assertNotNull("paged search capability not present", capPage); } @Test public void test500FetchObject() throws Exception { final String TEST_NAME = "test500FetchObject"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN ResourceAttributeContainer resourceObject = createResourceObject("uid=Teell,ou=People,dc=example,dc=com", "Teell William", "Teell"); OperationResult addResult = new OperationResult(this.getClass().getName() + "." + TEST_NAME); PrismObject<ShadowType> shadow = wrapInShadow(ShadowType.class, resourceObject); // Add a testing object cc.addObject(shadow, null, addResult); ObjectClassComplexTypeDefinition accountDefinition = resourceObject.getDefinition().getComplexTypeDefinition(); Collection<ResourceAttribute<?>> identifiers = resourceObject.getIdentifiers(); // Determine object class from the schema ResourceObjectIdentification identification = new ResourceObjectIdentification(accountDefinition, identifiers); OperationResult result = new OperationResult(this.getClass().getName() + "." + TEST_NAME); // WHEN PrismObject<ShadowType> ro = cc.fetchObject(ShadowType.class, identification, null, result); // THEN AssertJUnit.assertNotNull(ro); System.out.println("Fetched object " + ro); System.out.println("Result:"); System.out.println(result.debugDump()); } @Test public void test510Search() throws Exception { final String TEST_NAME = "test510Search"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN ObjectClassComplexTypeDefinition accountDefinition = resourceSchema.findObjectClassDefinition( ProvisioningTestUtil.OBJECT_CLASS_INETORGPERSON_NAME); // Determine object class from the schema ResultHandler<ShadowType> handler = new ResultHandler<ShadowType>() { @Override public boolean handle(PrismObject<ShadowType> object) { System.out.println("Search: found: " + object); return true; } }; OperationResult result = new OperationResult(this.getClass().getName() + "." + TEST_NAME); // WHEN cc.search(accountDefinition, new ObjectQuery(), handler, null, null, null, result); // THEN } @Test public void test600CreateAccountWithPassword() throws Exception { final String TEST_NAME = "test600CreateAccountWithPassword"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN ResourceAttributeContainer resourceObject = createResourceObject( "uid=lechuck,ou=people,dc=example,dc=com", "Ghost Pirate LeChuck", "LeChuck"); Set<Operation> additionalOperations = new HashSet<Operation>(); ProtectedStringType ps = protector.encryptString("t4k30v3rTh3W0rld"); // PasswordChangeOperation passOp = new PasswordChangeOperation(ps); // additionalOperations.add(passOp); OperationResult addResult = new OperationResult(this.getClass().getName() + "." + TEST_NAME); PrismObject<ShadowType> shadow = wrapInShadow(ShadowType.class, resourceObject); CredentialsType credentials = new CredentialsType(); PasswordType pass = new PasswordType(); pass.setValue(ps); credentials.setPassword(pass); shadow.asObjectable().setCredentials(credentials); // WHEN cc.addObject(shadow, additionalOperations, addResult); // THEN String entryUuid = (String) resourceObject.getIdentifier().getValue().getValue(); SearchResultEntry entry = openDJController.searchAndAssertByEntryUuid(entryUuid); display("Entry before change", entry); String passwordAfter = OpenDJController.getAttributeValue(entry, "userPassword"); assertNotNull(passwordAfter); System.out.println("Changed password: "******"test610ChangePassword"; TestUtil.displayTestTile(this, TEST_NAME); // GIVEN ResourceAttributeContainer resourceObject = createResourceObject("uid=drake,ou=People,dc=example,dc=com", "Sir Francis Drake", "Drake"); PrismObject<ShadowType> shadow = wrapInShadow(ShadowType.class, resourceObject); OperationResult addResult = new OperationResult(this.getClass().getName() + "." + TEST_NAME); // Add a testing object cc.addObject(shadow, null, addResult); String entryUuid = (String) resourceObject.getIdentifier().getValue().getValue(); SearchResultEntry entry = openDJController.searchAndAssertByEntryUuid(entryUuid); display("Entry before change", entry); String passwordBefore = OpenDJController.getAttributeValue(entry, "userPassword"); // We have set no password during create, therefore the password should // be empty assertNull(passwordBefore); ObjectClassComplexTypeDefinition accountDefinition = resourceObject.getDefinition().getComplexTypeDefinition(); Collection<ResourceAttribute<?>> identifiers = resourceObject.getIdentifiers(); // Determine object class from the schema OperationResult result = new OperationResult(this.getClass().getName() + ".testFetchObject"); // WHEN Set<Operation> changes = new HashSet<Operation>(); ProtectedStringType passPs = protector.encryptString("salalala"); ItemDeltaType propMod = new ItemDeltaType(); // create modification path Document doc = DOMUtil.getDocument(); ItemPathType path = new ItemPathType("credentials/password/value"); // PropertyPath propPath = new PropertyPath(new // PropertyPath(ResourceObjectShadowType.F_CREDENTIALS), CredentialsType.F_PASSWORD); propMod.setPath(path); // set the replace value MapXNode passPsXnode = prismContext.getBeanConverter().marshalProtectedDataType(passPs); RawType value = new RawType(passPsXnode, prismContext); propMod.getValue().add(value); // set the modificaion type propMod.setModificationType(ModificationTypeType.REPLACE); PropertyDelta passDelta = (PropertyDelta) DeltaConvertor.createItemDelta(propMod, shadow.getDefinition()); PropertyModificationOperation passwordModification = new PropertyModificationOperation(passDelta); changes.add(passwordModification); // PasswordChangeOperation passwordChange = new PasswordChangeOperation(passPs); // changes.add(passwordChange); cc.modifyObject(accountDefinition, identifiers, changes, result); // THEN entry = openDJController.searchAndAssertByEntryUuid(entryUuid); display("Entry after change", entry); String passwordAfter = OpenDJController.getAttributeValue(entry, "userPassword"); assertNotNull(passwordAfter); System.out.println("Account password: "******"sn")); ResourceAttribute roa = road.instantiate(); roa.setValue(new PrismPropertyValue(sn)); resourceObject.add(roa); road = accountDefinition.findAttributeDefinition( new QName(ResourceTypeUtil.getResourceNamespace(resourceType), "cn")); roa = road.instantiate(); roa.setValue(new PrismPropertyValue(cn)); resourceObject.add(roa); road = accountDefinition.findAttributeDefinition( new QName( ResourceTypeUtil.getResourceNamespace(resourceType), ProvisioningTestUtil.RESOURCE_OPENDJ_SECONDARY_IDENTIFIER_LOCAL_NAME)); roa = road.instantiate(); roa.setValue(new PrismPropertyValue(dn)); resourceObject.add(roa); return resourceObject; } private <T extends ShadowType> PrismObject<T> wrapInShadow( Class<T> type, ResourceAttributeContainer resourceObject) throws SchemaException { PrismObjectDefinition<T> shadowDefinition = getShadowDefinition(type); PrismObject<T> shadow = shadowDefinition.instantiate(); resourceObject.setElementName(ShadowType.F_ATTRIBUTES); shadow.getValue().add(resourceObject); return shadow; } private <T extends ShadowType> PrismObjectDefinition<T> getShadowDefinition(Class<T> type) { return prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(type); } }
/** @author semancik */ @Component public class ModelDiagController implements ModelDiagnosticService { public static final String CLASS_NAME_WITH_DOT = ModelDiagController.class.getName() + "."; private static final String REPOSITORY_SELF_TEST_USER = CLASS_NAME_WITH_DOT + "repositorySelfTest.user"; private static final String NAME_PREFIX = "selftest"; private static final int NAME_RANDOM_LENGTH = 5; private static final String USER_FULL_NAME = "Grăfula Fèlix Teleke z Tölökö"; private static final String USER_GIVEN_NAME = "Fëľïx"; private static final String USER_FAMILY_NAME = "Ţæĺêké"; private static final String[] USER_ORGANIZATION = { "COMITATVS NOBILITVS HVNGARIÆ", "Salsa Verde ğomorula prïvatûła" }; private static final String[] USER_EMPLOYEE_TYPE = {"Ģŗąfųŀą", "CANTATOR"}; private static final String INSANE_NATIONAL_STRING = "Pørúga ném nå väšȍm apârátula"; private static final Trace LOGGER = TraceManager.getTrace(ModelDiagController.class); @Autowired(required = true) private PrismContext prismContext; @Autowired(required = true) @Qualifier("repositoryService") private transient RepositoryService repositoryService; @Autowired(required = true) private ProvisioningService provisioningService; private RandomString randomString; ModelDiagController() { randomString = new RandomString(NAME_RANDOM_LENGTH, true); } /* (non-Javadoc) * @see com.evolveum.midpoint.model.api.ModelDiagnosticService#getRepositoryDiag(com.evolveum.midpoint.task.api.Task, com.evolveum.midpoint.schema.result.OperationResult) */ @Override public RepositoryDiag getRepositoryDiag(Task task, OperationResult parentResult) { return repositoryService.getRepositoryDiag(); } /* (non-Javadoc) * @see com.evolveum.midpoint.model.api.ModelDiagnosticService#repositorySelfTest(com.evolveum.midpoint.task.api.Task) */ @Override public OperationResult repositorySelfTest(Task task) { OperationResult testResult = new OperationResult(REPOSITORY_SELF_TEST); // Give repository chance to run its own self-test if available repositoryService.repositorySelfTest(testResult); repositorySelfTestUser(task, testResult); testResult.computeStatus(); return testResult; } @Override public OperationResult provisioningSelfTest(Task task) { OperationResult testResult = new OperationResult(PROVISIONING_SELF_TEST); // Give provisioning chance to run its own self-test provisioningService.provisioningSelfTest(testResult, task); testResult.computeStatus(); return testResult; } private void repositorySelfTestUser(Task task, OperationResult testResult) { OperationResult result = testResult.createSubresult(REPOSITORY_SELF_TEST_USER); PrismObject<UserType> user = getObjectDefinition(UserType.class).instantiate(); UserType userType = user.asObjectable(); String name = generateRandomName(); PolyStringType namePolyStringType = toPolyStringType(name); userType.setName(namePolyStringType); result.addContext("name", name); userType.setDescription(SelfTestData.POLICIJA); userType.setFullName(toPolyStringType(USER_FULL_NAME)); userType.setGivenName(toPolyStringType(USER_GIVEN_NAME)); userType.setFamilyName(toPolyStringType(USER_FAMILY_NAME)); userType.setTitle(toPolyStringType(INSANE_NATIONAL_STRING)); userType.getEmployeeType().add(USER_EMPLOYEE_TYPE[0]); userType.getEmployeeType().add(USER_EMPLOYEE_TYPE[1]); userType.getOrganization().add(toPolyStringType(USER_ORGANIZATION[0])); userType.getOrganization().add(toPolyStringType(USER_ORGANIZATION[1])); String oid; try { oid = repositoryService.addObject(user, null, result); } catch (ObjectAlreadyExistsException e) { result.recordFatalError(e); return; } catch (SchemaException e) { result.recordFatalError(e); return; } catch (RuntimeException e) { result.recordFatalError(e); return; } try { { OperationResult subresult = result.createSubresult(result.getOperation() + ".getObject"); PrismObject<UserType> userRetrieved; try { userRetrieved = repositoryService.getObject(UserType.class, oid, null, subresult); } catch (ObjectNotFoundException e) { result.recordFatalError(e); return; } catch (SchemaException e) { result.recordFatalError(e); return; } catch (RuntimeException e) { result.recordFatalError(e); return; } if (LOGGER.isTraceEnabled()) { LOGGER.trace("Self-test:user getObject:\n{}", userRetrieved.debugDump()); } checkUser(userRetrieved, name, subresult); subresult.recordSuccessIfUnknown(); } { OperationResult subresult = result.createSubresult(result.getOperation() + ".searchObjects.fullName"); try { ObjectQuery query = new ObjectQuery(); ObjectFilter filter = EqualFilter.createEqual( UserType.F_FULL_NAME, UserType.class, prismContext, null, toPolyString(USER_FULL_NAME)); query.setFilter(filter); subresult.addParam("query", query); List<PrismObject<UserType>> foundObjects = repositoryService.searchObjects(UserType.class, query, null, subresult); if (LOGGER.isTraceEnabled()) { LOGGER.trace("Self-test:user searchObjects:\n{}", DebugUtil.debugDump(foundObjects)); } assertSingleSearchResult("user", foundObjects, subresult); PrismObject<UserType> userRetrieved = foundObjects.iterator().next(); checkUser(userRetrieved, name, subresult); subresult.recordSuccessIfUnknown(); } catch (SchemaException e) { subresult.recordFatalError(e); return; } catch (RuntimeException e) { subresult.recordFatalError(e); return; } } // MID-1116 { OperationResult subresult = result.createSubresult(result.getOperation() + ".searchObjects.employeeType"); try { ObjectQuery query = new ObjectQuery(); ObjectFilter filter = EqualFilter.createEqual( UserType.F_EMPLOYEE_TYPE, UserType.class, prismContext, null, USER_EMPLOYEE_TYPE[0]); query.setFilter(filter); subresult.addParam("query", query); List<PrismObject<UserType>> foundObjects = repositoryService.searchObjects(UserType.class, query, null, subresult); if (LOGGER.isTraceEnabled()) { LOGGER.trace("Self-test:user searchObjects:\n{}", DebugUtil.debugDump(foundObjects)); } assertSingleSearchResult("user", foundObjects, subresult); PrismObject<UserType> userRetrieved = foundObjects.iterator().next(); checkUser(userRetrieved, name, subresult); subresult.recordSuccessIfUnknown(); } catch (SchemaException e) { subresult.recordFatalError(e); return; } catch (RuntimeException e) { subresult.recordFatalError(e); return; } } // MID-1116 { OperationResult subresult = result.createSubresult(result.getOperation() + ".searchObjects.organization"); try { ObjectQuery query = new ObjectQuery(); ObjectFilter filter = EqualFilter.createEqual( UserType.F_ORGANIZATION, UserType.class, prismContext, null, toPolyString(USER_ORGANIZATION[1])); query.setFilter(filter); subresult.addParam("query", query); List<PrismObject<UserType>> foundObjects = repositoryService.searchObjects(UserType.class, query, null, subresult); if (LOGGER.isTraceEnabled()) { LOGGER.trace("Self-test:user searchObjects:\n{}", DebugUtil.debugDump(foundObjects)); } assertSingleSearchResult("user", foundObjects, subresult); PrismObject<UserType> userRetrieved = foundObjects.iterator().next(); checkUser(userRetrieved, name, subresult); subresult.recordSuccessIfUnknown(); } catch (SchemaException e) { subresult.recordFatalError(e); return; } catch (RuntimeException e) { subresult.recordFatalError(e); return; } } } finally { try { repositoryService.deleteObject(UserType.class, oid, testResult); } catch (ObjectNotFoundException e) { result.recordFatalError(e); return; } catch (RuntimeException e) { result.recordFatalError(e); return; } result.computeStatus(); } } private void checkUser( PrismObject<UserType> userRetrieved, String name, OperationResult subresult) { checkUserPropertyPolyString(userRetrieved, UserType.F_NAME, subresult, name); checkUserProperty(userRetrieved, UserType.F_DESCRIPTION, subresult, SelfTestData.POLICIJA); checkUserPropertyPolyString(userRetrieved, UserType.F_FULL_NAME, subresult, USER_FULL_NAME); checkUserPropertyPolyString(userRetrieved, UserType.F_GIVEN_NAME, subresult, USER_GIVEN_NAME); checkUserPropertyPolyString(userRetrieved, UserType.F_FAMILY_NAME, subresult, USER_FAMILY_NAME); checkUserPropertyPolyString(userRetrieved, UserType.F_TITLE, subresult, INSANE_NATIONAL_STRING); checkUserProperty(userRetrieved, UserType.F_EMPLOYEE_TYPE, subresult, USER_EMPLOYEE_TYPE); checkUserPropertyPolyString( userRetrieved, UserType.F_ORGANIZATION, subresult, USER_ORGANIZATION); } private void assertSingleSearchResult( String objectTypeMessage, List<PrismObject<UserType>> foundObjects, OperationResult parentResult) { OperationResult result = parentResult.createSubresult(parentResult.getOperation() + ".numberOfResults"); assertTrue("Found no " + objectTypeMessage, !foundObjects.isEmpty(), result); assertTrue( "Expected to find a single " + objectTypeMessage + " but found " + foundObjects.size(), foundObjects.size() == 1, result); result.recordSuccessIfUnknown(); } private <O extends ObjectType, T> void checkUserProperty( PrismObject<O> object, QName propQName, OperationResult parentResult, T... expectedValues) { String propName = propQName.getLocalPart(); OperationResult result = parentResult.createSubresult(parentResult.getOperation() + "." + propName); PrismProperty<T> prop = object.findProperty(propQName); Collection<T> actualValues = prop.getRealValues(); result.addArbitraryCollectionAsParam("actualValues", actualValues); assertMultivalue("User, property '" + propName + "'", expectedValues, actualValues, result); result.recordSuccessIfUnknown(); } private <T> void assertMultivalue( String message, T expectedVals[], Collection<T> actualVals, OperationResult result) { if (expectedVals.length != actualVals.size()) { fail( message + ": expected " + expectedVals.length + " values but has " + actualVals.size() + " values: " + actualVals, result); return; } for (T expected : expectedVals) { boolean found = false; for (T actual : actualVals) { if (expected.equals(actual)) { found = true; break; } } if (!found) { fail( message + ": expected value '" + expected + "' not found in actual values " + actualVals, result); return; } } } private <O extends ObjectType> void checkUserPropertyPolyString( PrismObject<O> object, QName propQName, OperationResult parentResult, String... expectedValues) { String propName = propQName.getLocalPart(); OperationResult result = parentResult.createSubresult(parentResult.getOperation() + "." + propName); PrismProperty<PolyString> prop = object.findProperty(propQName); Collection<PolyString> actualValues = prop.getRealValues(); result.addArbitraryCollectionAsParam("actualValues", actualValues); assertMultivaluePolyString( "User, property '" + propName + "'", expectedValues, actualValues, result); result.recordSuccessIfUnknown(); } private void assertMultivaluePolyString( String message, String expectedOrigs[], Collection<PolyString> actualPolyStrings, OperationResult result) { if (expectedOrigs.length != actualPolyStrings.size()) { fail( message + ": expected " + expectedOrigs.length + " values but has " + actualPolyStrings.size() + " values: " + actualPolyStrings, result); return; } for (String expectedOrig : expectedOrigs) { boolean found = false; for (PolyString actualPolyString : actualPolyStrings) { if (expectedOrig.equals(actualPolyString.getOrig())) { found = true; assertEquals( message + ", norm", polyStringNorm(expectedOrig), actualPolyString.getNorm(), result); break; } } if (!found) { fail( message + ": expected value '" + expectedOrig + "' not found in actual values " + actualPolyStrings, result); return; } } } private void assertPolyString( String message, String expectedOrig, PolyString actualPolyString, OperationResult result) { assertEquals(message + ", orig", expectedOrig, actualPolyString.getOrig(), result); assertEquals( message + ", norm", polyStringNorm(expectedOrig), actualPolyString.getNorm(), result); } private void assertPolyStringType( String message, String expectedName, PolyStringType actualPolyStringType, OperationResult result) { assertEquals(message + ", orig", expectedName, actualPolyStringType.getOrig(), result); assertEquals( message + ", norm", polyStringNorm(expectedName), actualPolyStringType.getNorm(), result); } private String polyStringNorm(String orig) { return prismContext.getDefaultPolyStringNormalizer().normalize(orig); } private void assertTrue(String message, boolean condition, OperationResult result) { if (!condition) { fail(message, result); } } private void assertEquals( String message, Object expected, Object actual, OperationResult result) { if (!MiscUtil.equals(expected, actual)) { fail(message + "; expected " + expected + ", actual " + actual, result); } } private void fail(String message, OperationResult result) { result.recordFatalError(message); LOGGER.error("Repository self-test assertion failed: {}", message); } private String generateRandomName() { return NAME_PREFIX + randomString.nextString(); } private PolyStringType toPolyStringType(String orig) { PolyStringType polyStringType = new PolyStringType(); polyStringType.setOrig(orig); return polyStringType; } private PolyString toPolyString(String orig) { PolyString polyString = new PolyString(orig); polyString.recompute(prismContext.getDefaultPolyStringNormalizer()); return polyString; } private <T extends ObjectType> PrismObjectDefinition<T> getObjectDefinition(Class<T> type) { return prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(type); } }
public class ReportFunctions { private static final Trace LOGGER = TraceManager.getTrace(ReportFunctions.class); private PrismContext prismContext; private ModelService model; private TaskManager taskManager; private AuditService auditService; public ReportFunctions( PrismContext prismContext, ModelService modelService, TaskManager taskManager, AuditService auditService) { this.prismContext = prismContext; this.model = modelService; this.taskManager = taskManager; this.auditService = auditService; } public <O extends ObjectType> O resolveObject(ObjectReferenceType ref) { Validate.notNull(ref.getOid(), "Object oid must not be null"); Validate.notNull(ref.getType(), "Object type must not be null"); Class type = prismContext.getSchemaRegistry().determineCompileTimeClass(ref.getType()); return resolveObject(type, ref.getOid()); } public <O extends ObjectType> O resolveObject(Class type, String oid) { Task task = taskManager.createTaskInstance(); OperationResult parentResult = task.getResult(); PrismObject<O> obj; try { obj = model.getObject( type, oid, SelectorOptions.createCollection(GetOperationOptions.createResolveNames()), task, parentResult); return obj.asObjectable(); } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | CommunicationException | ConfigurationException e) { // TODO Auto-generated catch block LOGGER.error("Could not get object with oid " + oid + ". Reason: " + e.getMessage()); } return null; } public <O extends ObjectType> List<PrismObject<O>> resolveLinkRefs( Collection<ObjectReferenceType> refs, Class type) { List<PrismObject<O>> objects = new ArrayList<>(); for (ObjectReferenceType ref : refs) { Class clazz = getClassForType(ref.getType()); if (!clazz.equals(type)) { continue; } Task task = taskManager.createTaskInstance(); OperationResult parentResult = task.getResult(); try { PrismObject<O> obj = model.getObject( type, ref.getOid(), SelectorOptions.createCollection(GetOperationOptions.createResolveNames()), task, parentResult); objects.add(obj); } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | CommunicationException | ConfigurationException e) { // TODO Auto-generated catch block LOGGER.error( "Could not get object with oid " + ref.getOid() + ". Reason: " + e.getMessage()); } } return objects; } public String resolveRefName(ObjectReferenceType ref) { if (ref == null) { return null; } PrismReferenceValue refValue = ref.asReferenceValue(); Object name = refValue.getTargetName() != null ? ref.getTargetName().getOrig() : null; if (!(name instanceof String)) { LOGGER.error("Couldn't resolve object name"); } return (String) name; } public List<PrismObject<RoleType>> resolveRoles(Collection<AssignmentType> assignments) { return resolveAssignments(assignments, RoleType.class); } public List<PrismObject<OrgType>> resolveOrgs(Collection<AssignmentType> assignments) { return resolveAssignments(assignments, OrgType.class); } public List<PrismObject<RoleType>> resolveRoles(AssignmentType assignments) { return resolveAssignments(assignments, RoleType.class); } public List<PrismObject<OrgType>> resolveOrgs(AssignmentType assignments) { return resolveAssignments(assignments, OrgType.class); } public <O extends ObjectType> List<PrismObject<O>> resolveAssignments( AssignmentType assignment, Class<O> type) { List<AssignmentType> assignments = new ArrayList<>(); assignments.add(assignment); return resolveAssignments(assignments, type); } public <O extends ObjectType> List<PrismObject<O>> resolveAssignments( Collection<AssignmentType> assignments, Class<O> type) { List<PrismObject<O>> resolvedAssignments = new ArrayList<>(); if (assignments == null) { return resolvedAssignments; } for (AssignmentType assignment : assignments) { Class clazz = null; String oid = null; if (assignment.getTargetRef() != null) { clazz = getClassForType(assignment.getTargetRef().getType()); oid = assignment.getTargetRef().getOid(); } else if (assignment.getTarget() != null) { clazz = assignment.getTarget().getClass(); } else if (assignment.getTenantRef() != null) { clazz = getClassForType(assignment.getTenantRef().getType()); oid = assignment.getTenantRef().getOid(); } if (clazz == null && assignment.getConstruction() != null) { continue; } else { LOGGER.debug("Could not resolve assignment for type {}. No target type defined.", type); } if (!clazz.equals(type)) { continue; } if (assignment.getTarget() != null) { resolvedAssignments.add(assignment.getTarget().asPrismObject()); continue; } Task task = taskManager.createTaskInstance(); try { PrismObject<O> obj = model.getObject(type, oid, null, task, task.getResult()); resolvedAssignments.add(obj); } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | CommunicationException | ConfigurationException e) { LOGGER.error("Could not get object with oid " + oid + ". Reason: " + e.getMessage()); } } return resolvedAssignments; } public List<AuditEventRecord> searchAuditRecords(String query, Map<String, Object> params) { if (StringUtils.isBlank(query)) { return new ArrayList<>(); } Map<String, Object> resultSet = new HashMap<String, Object>(); Set<Entry<String, Object>> paramSet = params.entrySet(); for (Entry<String, Object> p : paramSet) { if (p.getValue() instanceof AuditEventTypeType) { resultSet.put( p.getKey(), AuditEventType.toAuditEventType((AuditEventTypeType) p.getValue())); } else if (p.getValue() instanceof AuditEventStageType) { resultSet.put( p.getKey(), AuditEventStage.toAuditEventStage((AuditEventStageType) p.getValue())); } else { resultSet.put(p.getKey(), p.getValue()); } } return auditService.listRecords(query, resultSet); } public UserType getShadowOwner(String shadowOid) { Task task = taskManager.createTaskInstance(); try { PrismObject<UserType> owner = model.findShadowOwner(shadowOid, task, task.getResult()); return owner.asObjectable(); } catch (ObjectNotFoundException | SecurityViolationException | SchemaException | ConfigurationException e) { // TODO Auto-generated catch block LOGGER.error( "Could not find owner for shadow with oid " + shadowOid + ". Reason: " + e.getMessage()); } return null; } private Class getClassForType(QName type) { return prismContext.getSchemaRegistry().determineCompileTimeClass(type); } <T extends ObjectType> List<T> searchObjects(Class<T> type, ObjectQuery query) { List<T> ret = new ArrayList(); Task task = taskManager.createTaskInstance(); try { List<PrismObject<T>> list = model.searchObjects(type, query, null, task, task.getResult()).getList(); for (PrismObject<T> po : list) { ret.add(po.asObjectable()); } } catch (SchemaException | ObjectNotFoundException | SecurityViolationException | CommunicationException | ConfigurationException e) { LOGGER.error( "Could not search objects of type: " + type + " with query " + query + ". Reason: " + e.getMessage()); } return ret; } <C extends Containerable, T> EqualFilter<T> createEqualFilter( QName propertyName, Class<C> type, T realValues) throws SchemaException { return EqualFilter.createEqual(propertyName, type, prismContext, realValues); } <C extends Containerable, T> EqualFilter<T> createEqualFilter( ItemPath propertyPath, Class<C> type, T realValues) throws SchemaException { return EqualFilter.createEqual(propertyPath, type, prismContext, realValues); } <O extends Containerable> RefFilter createReferenceEqualFilter( QName propertyName, Class<O> type, String... oids) { return RefFilter.createReferenceEqual(propertyName, type, prismContext, oids); } <O extends Containerable> RefFilter createReferenceEqualFilter( ItemPath propertyPath, Class<O> type, String... oids) throws SchemaException { return RefFilter.createReferenceEqual(propertyPath, type, prismContext, oids); } Object parseObjectFromXML(String xml) throws SchemaException { return prismContext.parseAnyData(xml, PrismContext.LANG_XML); } /** * Retrieves all definitions. Augments them by count of campaigns (all + open ones). * * <p>TODO query parameters, customizable sorting definitions and campaigns counts are expected to * be low, so we can afford to go through all of them here */ public Collection<PrismObject<AccessCertificationDefinitionForReportType>> searchCertificationDefinitions() throws ConfigurationException, SchemaException, ObjectNotFoundException, CommunicationException, SecurityViolationException { Task task = taskManager.createTaskInstance(); OperationResult result = task.getResult(); Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(GetOperationOptions.createResolveNames()); List<PrismObject<AccessCertificationDefinitionType>> definitions = model.searchObjects(AccessCertificationDefinitionType.class, null, options, task, result); final Map<String, PrismObject<AccessCertificationDefinitionForReportType>> definitionsForReportMap = new HashMap<>(); for (PrismObject<AccessCertificationDefinitionType> definition : definitions) { // create subclass with the values copied from the superclass PrismObject<AccessCertificationDefinitionForReportType> definitionForReport = prismContext .createObjectable(AccessCertificationDefinitionForReportType.class) .asPrismObject(); for (Item<?, ?> item : definition.getValue().getItems()) { definitionForReport.getValue().add(item.clone()); } definitionsForReportMap.put(definition.getOid(), definitionForReport); } ResultHandler<AccessCertificationCampaignType> handler = new ResultHandler<AccessCertificationCampaignType>() { @Override public boolean handle( PrismObject<AccessCertificationCampaignType> campaignObject, OperationResult parentResult) { AccessCertificationCampaignType campaign = campaignObject.asObjectable(); if (campaign.getDefinitionRef() != null) { String definitionOid = campaign.getDefinitionRef().getOid(); PrismObject<AccessCertificationDefinitionForReportType> definitionObject = definitionsForReportMap.get(definitionOid); if (definitionObject != null) { AccessCertificationDefinitionForReportType definition = definitionObject.asObjectable(); int campaigns = definition.getCampaigns() != null ? definition.getCampaigns() : 0; definition.setCampaigns(campaigns + 1); AccessCertificationCampaignStateType state = campaign.getState(); if (state != AccessCertificationCampaignStateType.CREATED && state != CLOSED) { int openCampaigns = definition.getOpenCampaigns() != null ? definition.getOpenCampaigns() : 0; definition.setOpenCampaigns(openCampaigns + 1); } } } return true; } }; model.searchObjectsIterative( AccessCertificationCampaignType.class, null, handler, null, task, result); List<PrismObject<AccessCertificationDefinitionForReportType>> rv = new ArrayList<>(definitionsForReportMap.values()); Collections.sort( rv, new Comparator<PrismObject<AccessCertificationDefinitionForReportType>>() { @Override public int compare( PrismObject<AccessCertificationDefinitionForReportType> o1, PrismObject<AccessCertificationDefinitionForReportType> o2) { String n1 = o1.asObjectable().getName().getOrig(); String n2 = o2.asObjectable().getName().getOrig(); if (n1 == null) { n1 = ""; } return n1.compareTo(n2); } }); for (PrismObject<AccessCertificationDefinitionForReportType> defObject : rv) { AccessCertificationDefinitionForReportType def = defObject.asObjectable(); if (def.getCampaigns() == null) { def.setCampaigns(0); } if (def.getOpenCampaigns() == null) { def.setOpenCampaigns(0); } } return rv; } public List<PrismContainerValue<AccessCertificationCaseType>> getCertificationCampaignCases( String campaignName) throws SchemaException, SecurityViolationException, ConfigurationException, ObjectNotFoundException { List<AccessCertificationCaseType> cases = getCertificationCampaignCasesAsBeans(campaignName); return PrismContainerValue.toPcvList(cases); } private List<AccessCertificationCaseType> getCertificationCampaignCasesAsBeans( String campaignName) throws SchemaException, SecurityViolationException, ConfigurationException, ObjectNotFoundException { Task task = taskManager.createTaskInstance(); ObjectQuery query; if (StringUtils.isEmpty(campaignName)) { // query = null; return new ArrayList<>(); } else { query = QueryBuilder.queryFor(AccessCertificationCaseType.class, prismContext) .item(PrismConstants.T_PARENT, F_NAME) .eqPoly(campaignName, "") .matchingOrig() .asc( CertCampaignTypeUtil.getOrderBy( F_OBJECT_REF)) // TODO first by type then by name (not supported by the // repository as of now) .asc(CertCampaignTypeUtil.getOrderBy(F_TARGET_REF)) // the same .build(); } Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(GetOperationOptions.createResolveNames()); return model.searchContainers( AccessCertificationCaseType.class, query, options, task, task.getResult()); } public List<PrismContainerValue<AccessCertificationDecisionType>> getCertificationCampaignDecisions(String campaignName, Integer stageNumber) throws SchemaException, SecurityViolationException, ConfigurationException, ObjectNotFoundException { List<AccessCertificationCaseType> cases = getCertificationCampaignCasesAsBeans(campaignName); List<AccessCertificationDecisionType> decisions = new ArrayList<>(); for (AccessCertificationCaseType aCase : cases) { for (AccessCertificationDecisionType decision : aCase.getDecision()) { if (stageNumber == null || decision.getStageNumber() == stageNumber) { decisions.add(decision); } } } return PrismContainerValue.toPcvList(decisions); } public List<PrismObject<AccessCertificationCampaignType>> getCertificationCampaigns( Boolean alsoClosedCampaigns) throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException, SecurityViolationException { Task task = taskManager.createTaskInstance(); ObjectQuery query = QueryBuilder.queryFor(AccessCertificationCampaignType.class, prismContext) .asc(F_NAME) .build(); if (!Boolean.TRUE.equals(alsoClosedCampaigns)) { query.addFilter( QueryBuilder.queryFor(AccessCertificationCampaignType.class, prismContext) .not() .item(F_STATE) .eq(CLOSED) .buildFilter()); } Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(GetOperationOptions.createResolveNames()); options.add( SelectorOptions.create( AccessCertificationCampaignType.F_CASE, GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE))); return model.searchObjects( AccessCertificationCampaignType.class, query, options, task, task.getResult()); } }
@PageDescriptor(url = "/PasswordQuestions") public class PageMyPasswordQuestions extends PageAdminHome { private static final Trace LOGGER = TraceManager.getTrace(PageMyPasswordQuestions.class); private static final String DOT_CLASS = PageMyPasswordQuestions.class.getName() + "."; private static final String OPERATION_LOAD_USER = DOT_CLASS + "loaduser"; private static final String OPERATION_LOAD_QUESTION_POLICY = DOT_CLASS + "LOAD Question Policy"; private String ID_PASSWORD_QUESTIONS_PANEL = "pwdQuestionsPanel"; private static final String OPERATION_SAVE_QUESTIONS = "Save Security Questions"; private static final String ID_MAIN_FORM = "mainForm"; private static final String ID_BACK = "back"; private static final String ID_SAVE = "save"; private LoadableModel<ObjectWrapper> userModel; private List<MyPasswordQuestionsPanel> pqPanels; private IModel<PasswordQuestionsDto> model; private List<SecurityQuestionDefinitionType> policyQuestionList; private MyPasswordQuestionsPanel pwPanel; int questionNumber; public PageMyPasswordQuestions() { model = new LoadableModel<PasswordQuestionsDto>(false) { private static final long serialVersionUID = 1L; @Override protected PasswordQuestionsDto load() { return loadPageModel(); } }; initLayout(); } public PageMyPasswordQuestions(IModel<PasswordQuestionsDto> model) { this.model = model; initLayout(); } public PageMyPasswordQuestions(final PrismObject<UserType> userToEdit) { userModel = new LoadableModel<ObjectWrapper>(false) { @Override protected ObjectWrapper load() { return loadUserWrapper(userToEdit); } }; initLayout(); } private PasswordQuestionsDto loadPageModel() { LOGGER.debug("Loading user for Security Question Page."); PasswordQuestionsDto dto = new PasswordQuestionsDto(); OperationResult result = new OperationResult(OPERATION_LOAD_USER); try { String userOid = SecurityUtils.getPrincipalUser().getOid(); Task task = createSimpleTask(OPERATION_LOAD_USER); OperationResult subResult = result.createSubresult(OPERATION_LOAD_USER); PrismObject<UserType> user = getModelService().getObject(UserType.class, userOid, null, task, subResult); dto.setSecurityAnswers(createUsersSecurityQuestionsList(user)); subResult.recordSuccessIfUnknown(); } catch (Exception ex) { LoggingUtils.logExceptionOnDebugLevel( LOGGER, "Couldn't get user Questions, Probably not set yet", ex); } finally { result.recomputeStatus(); } return dto; } public List<SecurityQuestionAnswerDTO> createUsersSecurityQuestionsList( PrismObject<UserType> user) { LOGGER.debug("Security Questions Loading for user: "******"User SecurityQuestion ANswer List is Not null"); List<SecurityQuestionAnswerDTO> secQuestAnswListDTO = new ArrayList<SecurityQuestionAnswerDTO>(); for (Iterator iterator = secQuestAnsList.iterator(); iterator.hasNext(); ) { SecurityQuestionAnswerType securityQuestionAnswerType = (SecurityQuestionAnswerType) iterator.next(); Protector protector = getPrismContext().getDefaultProtector(); String decoded = ""; if (securityQuestionAnswerType.getQuestionAnswer().getEncryptedDataType() != null) { try { decoded = protector.decryptString(securityQuestionAnswerType.getQuestionAnswer()); } catch (EncryptionException e) { LoggingUtils.logException(LOGGER, "Couldn't decrypt user answer", e); } } // LOGGER.debug("SecAnswerIdentifier:"+securityQuestionAnswerType.getQuestionIdentifier()); secQuestAnswListDTO.add( new SecurityQuestionAnswerDTO( securityQuestionAnswerType.getQuestionIdentifier(), decoded)); } return secQuestAnswListDTO; } } return null; } public void initLayout() { Form mainForm = new Form(ID_MAIN_FORM); // question panel list pqPanels = new ArrayList<MyPasswordQuestionsPanel>(); OperationResult result = new OperationResult(OPERATION_LOAD_QUESTION_POLICY); try { Task task = getPageBase().createSimpleTask(OPERATION_LOAD_QUESTION_POLICY); OperationResult subResult = result.createSubresult(OPERATION_LOAD_QUESTION_POLICY); try { // PrismObject<SystemConfigurationType> config = getPageBase().getModelService().getObject( // SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value(), null, // task, result); CredentialsPolicyType credPolicy = getModelInteractionService().getCredentialsPolicy(null, null, result); // PrismObject<SecurityPolicyType> securityPolicy = // getModelService().getObject(SecurityPolicyType.class,config.asObjectable().getGlobalSecurityPolicyRef().getOid(), null, task, subResult); // Global Policy set question numbers if (credPolicy != null && credPolicy.getSecurityQuestions() != null) { questionNumber = credPolicy.getSecurityQuestions().getQuestionNumber(); // Actual Policy Question List policyQuestionList = credPolicy.getSecurityQuestions().getQuestion(); } else { questionNumber = 0; policyQuestionList = new ArrayList<SecurityQuestionDefinitionType>(); } } catch (Exception ex) { ex.printStackTrace(); /* List<SecurityQuestionAnswerDTO> userQuestionList= model.getObject().getSecurityAnswers(); int panelNumber=0; PrismObject<UserType> user = null; Collection options = SelectorOptions.createCollection(UserType.F_CREDENTIALS, GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE)); Task taskTwo = createSimpleTask("LOAD USER WRAPPER"); user = getModelService().getObject(UserType.class, SecurityUtils.getPrincipalUser().getOid(), options, taskTwo, result); OperationResult parentResult = new OperationResult(OPERATION_LOAD_QUESTION_POLICY); questionNumber = getModelInteractionService().getCredentialsPolicy(user, parentResult).getSecurityQuestions().getQuestionNumber(); policyQuestionList=getModelInteractionService().getCredentialsPolicy(user, parentResult).getSecurityQuestions().getQuestion(); if(userQuestionList==null){ executeAddingQuestions(questionNumber, 0, policyQuestionList); LOGGER.info(getModelInteractionService().getCredentialsPolicy(user, parentResult).getSecurityQuestions().getQuestionNumber().toString()); }else{ for(int userQuestint=0;userQuestint<userQuestionList.size();userQuestint++){ SecurityQuestionAnswerDTO answerDTO= checkIfQuestionisValid(userQuestionList.get(userQuestint), policyQuestionList); if (userQuestionList.get(userQuestint)!=null){ LOGGER.debug("Questitself"+userQuestionList.get(userQuestint).getQuestionItself()); MyPasswordQuestionsPanel panel=new MyPasswordQuestionsPanel(ID_PASSWORD_QUESTIONS_PANEL+ panelNumber,userQuestionList.get(userQuestint)); pqPanels.add(panel); panelNumber++; } } //TODO same questions check should be implemented } add(mainForm); mainForm.add(getPanels(pqPanels)); initButtons(mainForm); return; */ } /*User's Pre-Set Question List*/ List<SecurityQuestionAnswerDTO> userQuestionList = model.getObject().getSecurityAnswers(); /* check if user's set number of * questions matches the policy or not*/ // Case that policy have more than users's number of numbers if ((userQuestionList == null) || (questionNumber > userQuestionList.size())) { if (userQuestionList == null) { executeAddingQuestions(questionNumber, 0, policyQuestionList); // TODO same questions check should be implemented } else { executePasswordQuestionsAndAnswers( userQuestionList, policyQuestionList, userQuestionList.size()); // QUESTION NUMBER BIGGER THAN QUESTION LIST // rest of the questions int difference = questionNumber - userQuestionList.size(); executeAddingQuestions(difference, userQuestionList.size(), policyQuestionList); } } else if (questionNumber == userQuestionList.size()) { // QUESTION NUMBER EQUALS TO QUESTION LIST executePasswordQuestionsAndAnswers(userQuestionList, policyQuestionList, 0); // TODO PART2: Case that policy have smaller than users's number of numbers } else if (questionNumber < userQuestionList.size()) { // QUESTION NUMBER SMALLER THAN QUESTION LIST executePasswordQuestionsAndAnswers(userQuestionList, policyQuestionList, 0); // this part will be using at remove operation in the future /* int diff = userQuestionList.size()-questionNumber; for(Iterator iterator = userQuestionList.iterator(); iterator.hasNext();){ SecurityQuestionAnswerDTO element = (SecurityQuestionAnswerDTO)iterator.next(); for(int i=0; i<diff;i++){ if(element == userQuestionList.get(questionNumber+i)){ try{ //LOGGER.info("REMOVE"); iterator.remove(); } catch (UnsupportedOperationException uoe) { LOGGER.info(uoe.getStackTrace().toString()); } } } }*/ } } catch (Exception ex) { result.recordFatalError("Couldn't load system configuration.", ex); } add(mainForm); mainForm.add(getPanels(pqPanels)); initButtons(mainForm); } /** * method for adding questions to user credentials * * @author oguzhan * @param questionNumber * @param panelNumber * @param policyQuestionList */ public void executeAddingQuestions( int questionNumber, int panelNumber, List<SecurityQuestionDefinitionType> policyQuestionList) { LOGGER.debug("executeAddingQuestions"); for (int i = 0; i < questionNumber; i++) { // LOGGER.info("\n\n Adding panel element"); SecurityQuestionAnswerDTO a = new SecurityQuestionAnswerDTO( policyQuestionList.get(panelNumber).getIdentifier(), "", policyQuestionList.get(panelNumber).getQuestionText()); MyPasswordQuestionsPanel panel = new MyPasswordQuestionsPanel(ID_PASSWORD_QUESTIONS_PANEL + panelNumber, a); pqPanels.add(panel); panelNumber++; } } /** * method for get existing questions and answer from user credentials * * @author oguzhan * @param userQuestionList * @param policyQuestionList * @param panelNumber */ public void executePasswordQuestionsAndAnswers( List<SecurityQuestionAnswerDTO> userQuestionList, List<SecurityQuestionDefinitionType> policyQuestionList, int panelNumber) { int userQuest = 0; LOGGER.debug("executePasswordQuestionsAndAnswers"); for (Iterator iterator = policyQuestionList.iterator(); iterator.hasNext(); ) { /* Loop for finding the Existing Questions * and Answers according to Policy*/ SecurityQuestionDefinitionType securityQuestionDefinitionType = (SecurityQuestionDefinitionType) iterator.next(); // user's question List loop to match the questions for (int i = userQuest; i < userQuestionList.size(); i++) { if (userQuestionList .get(i) .getPwdQuestion() .trim() .compareTo(securityQuestionDefinitionType.getIdentifier().trim()) == 0) { SecurityQuestionAnswerDTO a = new SecurityQuestionAnswerDTO( userQuestionList.get(i).getPwdQuestion(), userQuestionList.get(i).getPwdAnswer(), userQuestionList.get(i).getQuestionItself()); a = checkIfQuestionisValidSingle(a, securityQuestionDefinitionType); MyPasswordQuestionsPanel panel = new MyPasswordQuestionsPanel(ID_PASSWORD_QUESTIONS_PANEL + panelNumber, a); pqPanels.add(panel); panelNumber++; userQuest++; break; } else if (userQuestionList .get(i) .getPwdQuestion() .trim() .compareTo(securityQuestionDefinitionType.getIdentifier().trim()) != 0) { SecurityQuestionAnswerDTO a = new SecurityQuestionAnswerDTO( policyQuestionList.get(panelNumber).getIdentifier(), "", policyQuestionList.get(panelNumber).getQuestionText()); a.setQuestionItself(securityQuestionDefinitionType.getQuestionText()); userQuestionList .get(i) .setPwdQuestion(securityQuestionDefinitionType.getIdentifier().trim()); MyPasswordQuestionsPanel panel = new MyPasswordQuestionsPanel(ID_PASSWORD_QUESTIONS_PANEL + panelNumber, a); pqPanels.add(panel); panelNumber++; userQuest++; break; } } } } public ListView<MyPasswordQuestionsPanel> getPanels(List<MyPasswordQuestionsPanel> p) { ListView lw = new ListView(ID_PASSWORD_QUESTIONS_PANEL, p) { @Override protected void populateItem(ListItem item) { item.add((MyPasswordQuestionsPanel) item.getModelObject()); } }; return lw; } public void initButtons(Form mainForm) { AjaxSubmitButton save = new AjaxSubmitButton(ID_SAVE, createStringResource("PageBase.button.save")) { private static final long serialVersionUID = 1L; @Override protected void onSubmit(AjaxRequestTarget target, Form<?> form) { savePerformed(target); } }; mainForm.add(save); AjaxButton back = new AjaxButton(ID_BACK, createStringResource("PageBase.button.back")) { private static final long serialVersionUID = 1L; @Override public void onClick(AjaxRequestTarget target) { cancelPerformed(target); } }; mainForm.add(back); } private void savePerformed(AjaxRequestTarget target) { /* * Oguzhan: added target variable to the updateQuestions method. */ updateQuestions(SecurityUtils.getPrincipalUser().getOid(), target); } private void cancelPerformed(AjaxRequestTarget target) { if (WebMiscUtil.isAuthorized( AuthorizationConstants.AUTZ_UI_DASHBOARD_URL, AuthorizationConstants.AUTZ_UI_HOME_ALL_URL)) { setResponsePage(PageDashboard.class); } else { setResponsePage(PageSelfDashboard.class); } } private ObjectWrapper loadUserWrapper(PrismObject<UserType> userToEdit) { OperationResult result = new OperationResult(OPERATION_LOAD_USER); PrismObject<UserType> user = null; try { Collection options = SelectorOptions.createCollection( UserType.F_CREDENTIALS, GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE)); Task task = createSimpleTask(OPERATION_LOAD_USER); user = getModelService() .getObject( UserType.class, SecurityUtils.getPrincipalUser().getOid(), options, task, result); result.recordSuccess(); } catch (Exception ex) { result.recordFatalError("Couldn't get user.", ex); LoggingUtils.logException(LOGGER, "Couldn't load user PageMyQuestions", ex); } if (!result.isSuccess()) { showResultInSession(result); } if (user == null) { throw new RestartResponseException(PageDashboard.class); } ContainerStatus status = ContainerStatus.MODIFYING; ObjectWrapperFactory owf = new ObjectWrapperFactory(this); ObjectWrapper wrapper; try { wrapper = owf.createObjectWrapper("pageMyPasswordQuestions.userDetails", null, user, status); } catch (Exception ex) { result.recordFatalError("Couldn't get user.", ex); LoggingUtils.logException(LOGGER, "Couldn't load user", ex); wrapper = owf.createObjectWrapper( "pageMyPasswordQuestions.userDetails", null, user, null, null, status, false); } // ObjectWrapper wrapper = new ObjectWrapper("pageUser.userDetails", null, user, status); if (owf.getResult() != null && !WebMiscUtil.isSuccessOrHandledError(wrapper.getResult())) { showResultInSession(wrapper.getResult()); } return wrapper; } private SecurityQuestionAnswerDTO checkIfQuestionisValid( SecurityQuestionAnswerDTO questionIdentifier, List<SecurityQuestionDefinitionType> securityQuestionList) { for (Iterator iterator = securityQuestionList.iterator(); iterator.hasNext(); ) { SecurityQuestionDefinitionType securityQuestionDefinitionType = (SecurityQuestionDefinitionType) iterator.next(); LOGGER.debug("List For" + securityQuestionDefinitionType.getIdentifier().trim()); if (securityQuestionDefinitionType .getIdentifier() .trim() .equalsIgnoreCase((questionIdentifier.getPwdQuestion().trim()))) { questionIdentifier.setQuestionItself(securityQuestionDefinitionType.getQuestionText()); LOGGER.info(": TRUE QUESTION"); return questionIdentifier; } else { return null; } } return null; } private SecurityQuestionAnswerDTO checkIfQuestionisValidSingle( SecurityQuestionAnswerDTO questionIdentifier, SecurityQuestionDefinitionType securityQuestion) { if (securityQuestion .getIdentifier() .trim() .compareTo(questionIdentifier.getPwdQuestion().trim()) == 0) { questionIdentifier.setQuestionItself(securityQuestion.getQuestionText()); // LOGGER.info("\n\n: TRUE QUESTION"); return questionIdentifier; } else { return null; } } private void updateQuestions(String useroid, AjaxRequestTarget target) { Task task = createSimpleTask(OPERATION_SAVE_QUESTIONS); OperationResult result = new OperationResult(OPERATION_SAVE_QUESTIONS); SchemaRegistry registry = getPrismContext().getSchemaRegistry(); SecurityQuestionAnswerType[] answerTypeList = new SecurityQuestionAnswerType[questionNumber]; try { int listnum = 0; for (Iterator iterator = pqPanels.iterator(); iterator.hasNext(); ) { MyPasswordQuestionsPanel type = (MyPasswordQuestionsPanel) iterator.next(); SecurityQuestionAnswerType answerType = new SecurityQuestionAnswerType(); ProtectedStringType answer = new ProtectedStringType(); answer.setClearValue( ((TextField<String>) type.get(MyPasswordQuestionsPanel.F_ANSWER)).getModelObject()); answerType.setQuestionAnswer(answer); // used apache's unescapeHtml method for special chars like \' String results = StringEscapeUtils.unescapeHtml( (type.get(MyPasswordQuestionsPanel.F_QUESTION)).getDefaultModelObjectAsString()); answerType.setQuestionIdentifier(getQuestionIdentifierFromQuestion(results)); answerTypeList[listnum] = answerType; listnum++; } // if(answerTypeList.length !=) // fill in answerType data here ItemPath path = new ItemPath( UserType.F_CREDENTIALS, CredentialsType.F_SECURITY_QUESTIONS, SecurityQuestionsCredentialsType.F_QUESTION_ANSWER); ObjectDelta<UserType> objectDelta = ObjectDelta.createModificationReplaceContainer( UserType.class, useroid, path, getPrismContext(), answerTypeList); Collection<ObjectDelta<? extends ObjectType>> deltas = MiscSchemaUtil.createCollection(objectDelta); getModelService().executeChanges(deltas, null, task, result); /* System.out.println("getModel"); Collection<ObjectDelta<? extends ObjectType>> deltas = new ArrayList<ObjectDelta<? extends ObjectType>>(); PasswordQuestionsDto dto = new PasswordQuestionsDto(); PrismObjectDefinition objDef =registry.findObjectDefinitionByCompileTimeClass(UserType.class); Class<? extends ObjectType> type = UserType.class; final ItemPath valuePath = new ItemPath(SchemaConstantsGenerated.C_CREDENTIALS, CredentialsType.F_SECURITY_QUESTIONS, SecurityQuestionsCredentialsType.F_QUESTION_ANSWER); SecurityQuestionAnswerType secQuesAnsType= new SecurityQuestionAnswerType(); ProtectedStringType protStrType= new ProtectedStringType(); protStrType.setClearValue("deneme"); secQuesAnsType.setQuestionAnswer(protStrType); dto.setSecurityAnswers(new ArrayList<SecurityQuestionAnswerType>()); dto.getSecurityAnswers().add(secQuesAnsType); PropertyDelta delta = PropertyDelta.createModificationReplaceProperty(valuePath, objDef, dto.getSecurityAnswers().get(0).getQuestionAnswer()); // PropertyDelta delta= PropertyDelta.createModifica System.out.println("Update Questions3"); deltas.add(ObjectDelta.createModifyDelta(useroid, delta, type, getPrismContext())); System.out.println("Update Questions4"); getModelService().executeChanges(deltas, null, createSimpleTask(OPERATION_SAVE_QUESTIONS), result); System.out.println("Update Questions5"); */ success(getString("message.success")); target.add(getFeedbackPanel()); } catch (Exception ex) { error(getString("message.error")); target.add(getFeedbackPanel()); ex.printStackTrace(); } } private String getQuestionIdentifierFromQuestion(String questionItself) { // LOGGER.info("\n\n QUESTION: "+questionItself); for (Iterator iterator = policyQuestionList.iterator(); iterator.hasNext(); ) { SecurityQuestionDefinitionType securityQuestionDefinitionType = (SecurityQuestionDefinitionType) iterator.next(); if (questionItself.equalsIgnoreCase(securityQuestionDefinitionType.getQuestionText())) return securityQuestionDefinitionType.getIdentifier(); } return null; } public PageBase getPageBase() { return (PageBase) getPage(); } }
/** * This is very simple task handler that causes the process to enter WAITING for OTHER_TASKS state. * * @author Pavol Mederly */ public class WaitForTasksTaskHandler implements TaskHandler { private static final transient Trace LOGGER = TraceManager.getTrace(WaitForTasksTaskHandler.class); public static final String HANDLER_URI = "http://midpoint.evolveum.com/xml/ns/public/task/wait-for-tasks/handler-3"; private static WaitForTasksTaskHandler instance = null; private TaskManagerQuartzImpl taskManagerImpl; private WaitForTasksTaskHandler() {} public static void instantiateAndRegister(TaskManager taskManager) { if (instance == null) { instance = new WaitForTasksTaskHandler(); } taskManager.registerHandler(HANDLER_URI, instance); instance.taskManagerImpl = (TaskManagerQuartzImpl) taskManager; } @Override public TaskRunResult run(Task task) { OperationResult result = task.getResult().createSubresult(WaitForTasksTaskHandler.class.getName() + ".run"); result.recordInProgress(); LOGGER.info("WaitForTasksTaskHandler run starting; in task " + task.getName()); try { // todo resolve this brutal hack taskManagerImpl.pauseTask(task, TaskWaitingReason.OTHER, result); task.startWaitingForTasksImmediate(result); } catch (SchemaException e) { throw new SystemException( "Couldn't mark task as waiting for prerequisite tasks", e); // should not occur; will be handled by task runner } catch (ObjectNotFoundException e) { throw new SystemException( "Couldn't mark task as waiting for prerequisite tasks", e); // should not occur; will be handled by task runner } LOGGER.info("WaitForTasksTaskHandler run finishing; in task " + task.getName()); result.computeStatus(); TaskRunResult runResult = new TaskRunResult(); runResult.setOperationResult(result); runResult.setProgress(task.getProgress()); // not to overwrite task's progress runResult.setRunResultStatus(TaskRunResultStatus.FINISHED); return runResult; } @Override public Long heartbeat(Task task) { return null; // not to overwrite progress information! } @Override public void refreshStatus(Task task) {} @Override public String getCategoryName(Task task) { return null; // hopefully we will never need to derive category from this handler! (category is // filled-in when persisting tasks) } @Override public List<String> getCategoryNames() { return null; } }
/** @author semancik */ public class AbstractInitializedModelIntegrationTest extends AbstractConfiguredModelIntegrationTest { private static final int NUM_FUNCTIONAL_ORGS = 6; private static final int NUM_PROJECT_ORGS = 3; protected static final Trace LOGGER = TraceManager.getTrace(AbstractInitializedModelIntegrationTest.class); @Autowired(required = true) protected MappingFactory mappingFactory; @Autowired(required = true) protected Clockwork clockwork; protected ProfilingLensDebugListener lensDebugListener; protected UserType userTypeJack; protected UserType userTypeBarbossa; protected UserType userTypeGuybrush; protected UserType userTypeElaine; protected DummyResource dummyResource; protected DummyResourceContoller dummyResourceCtl; protected ResourceType resourceDummyType; protected PrismObject<ResourceType> resourceDummy; protected DummyResource dummyResourceRed; protected DummyResourceContoller dummyResourceCtlRed; protected ResourceType resourceDummyRedType; protected PrismObject<ResourceType> resourceDummyRed; protected DummyResource dummyResourceBlue; protected DummyResourceContoller dummyResourceCtlBlue; protected ResourceType resourceDummyBlueType; protected PrismObject<ResourceType> resourceDummyBlue; protected DummyResource dummyResourceWhite; protected DummyResourceContoller dummyResourceCtlWhite; protected ResourceType resourceDummyWhiteType; protected PrismObject<ResourceType> resourceDummyWhite; protected DummyResource dummyResourceYellow; protected DummyResourceContoller dummyResourceCtlYellow; protected ResourceType resourceDummyYellowType; protected PrismObject<ResourceType> resourceDummyYellow; protected DummyResource dummyResourceGreen; protected DummyResourceContoller dummyResourceCtlGreen; protected ResourceType resourceDummyGreenType; protected PrismObject<ResourceType> resourceDummyGreen; protected DummyResource dummyResourceBlack; protected DummyResourceContoller dummyResourceCtlBlack; protected ResourceType resourceDummyBlackType; protected PrismObject<ResourceType> resourceDummyBlack; protected DummyResource dummyResourceOrange; protected DummyResourceContoller dummyResourceCtlOrange; protected ResourceType resourceDummyOrangeType; protected PrismObject<ResourceType> resourceDummyOrange; protected DummyResource dummyResourceUpcase; protected DummyResourceContoller dummyResourceCtlUpcase; protected ResourceType resourceDummyUpcaseType; protected PrismObject<ResourceType> resourceDummyUpcase; protected ResourceType resourceDummySchemalessType; protected PrismObject<ResourceType> resourceDummySchemaless; public AbstractInitializedModelIntegrationTest() { super(); } @Override public void initSystem(Task initTask, OperationResult initResult) throws Exception { LOGGER.trace("initSystem"); super.initSystem(initTask, initResult); mappingFactory.setProfiling(true); lensDebugListener = new ProfilingLensDebugListener(); clockwork.setDebugListener(lensDebugListener); // Resources dummyResourceCtl = DummyResourceContoller.create(null); dummyResourceCtl.extendSchemaPirate(); dummyResource = dummyResourceCtl.getDummyResource(); dummyResourceCtl.addAttrDef( dummyResource.getAccountObjectClass(), DUMMY_ACCOUNT_ATTRIBUTE_SEA_NAME, String.class, false, false); resourceDummy = importAndGetObjectFromFile( ResourceType.class, getResourceDummyFile(), RESOURCE_DUMMY_OID, initTask, initResult); resourceDummyType = resourceDummy.asObjectable(); dummyResourceCtl.setResource(resourceDummy); dummyResourceCtlRed = DummyResourceContoller.create(RESOURCE_DUMMY_RED_NAME, resourceDummyRed); dummyResourceCtlRed.extendSchemaPirate(); dummyResourceRed = dummyResourceCtlRed.getDummyResource(); resourceDummyRed = importAndGetObjectFromFile( ResourceType.class, RESOURCE_DUMMY_RED_FILE, RESOURCE_DUMMY_RED_OID, initTask, initResult); resourceDummyRedType = resourceDummyRed.asObjectable(); dummyResourceCtlRed.setResource(resourceDummyRed); dummyResourceCtlBlue = DummyResourceContoller.create(RESOURCE_DUMMY_BLUE_NAME, resourceDummyBlue); dummyResourceCtlBlue.extendSchemaPirate(); dummyResourceBlue = dummyResourceCtlBlue.getDummyResource(); resourceDummyBlue = importAndGetObjectFromFile( ResourceType.class, getResourceDummyBlueFile(), RESOURCE_DUMMY_BLUE_OID, initTask, initResult); resourceDummyBlueType = resourceDummyBlue.asObjectable(); dummyResourceCtlBlue.setResource(resourceDummyBlue); dummyResourceCtlWhite = DummyResourceContoller.create(RESOURCE_DUMMY_WHITE_NAME, resourceDummyWhite); dummyResourceCtlWhite.extendSchemaPirate(); dummyResourceWhite = dummyResourceCtlWhite.getDummyResource(); resourceDummyWhite = importAndGetObjectFromFile( ResourceType.class, RESOURCE_DUMMY_WHITE_FILENAME, RESOURCE_DUMMY_WHITE_OID, initTask, initResult); resourceDummyWhiteType = resourceDummyWhite.asObjectable(); dummyResourceCtlWhite.setResource(resourceDummyWhite); dummyResourceCtlYellow = DummyResourceContoller.create(RESOURCE_DUMMY_YELLOW_NAME, resourceDummyYellow); dummyResourceCtlYellow.extendSchemaPirate(); dummyResourceYellow = dummyResourceCtlYellow.getDummyResource(); resourceDummyYellow = importAndGetObjectFromFile( ResourceType.class, RESOURCE_DUMMY_YELLOW_FILENAME, RESOURCE_DUMMY_YELLOW_OID, initTask, initResult); resourceDummyYellowType = resourceDummyYellow.asObjectable(); dummyResourceCtlYellow.setResource(resourceDummyYellow); dummyResourceCtlGreen = DummyResourceContoller.create(RESOURCE_DUMMY_GREEN_NAME, resourceDummyGreen); dummyResourceCtlGreen.extendSchemaPirate(); dummyResourceGreen = dummyResourceCtlGreen.getDummyResource(); resourceDummyGreen = importAndGetObjectFromFile( ResourceType.class, getResourceDummyGreenFile(), RESOURCE_DUMMY_GREEN_OID, initTask, initResult); resourceDummyGreenType = resourceDummyGreen.asObjectable(); dummyResourceCtlGreen.setResource(resourceDummyGreen); dummyResourceCtlBlack = DummyResourceContoller.create(RESOURCE_DUMMY_BLACK_NAME, resourceDummyBlack); dummyResourceCtlBlack.extendSchemaPirate(); dummyResourceBlack = dummyResourceCtlBlack.getDummyResource(); resourceDummyBlack = importAndGetObjectFromFile( ResourceType.class, RESOURCE_DUMMY_BLACK_FILENAME, RESOURCE_DUMMY_BLACK_OID, initTask, initResult); resourceDummyBlackType = resourceDummyBlack.asObjectable(); dummyResourceCtlBlack.setResource(resourceDummyBlack); dummyResourceCtlOrange = DummyResourceContoller.create(RESOURCE_DUMMY_ORANGE_NAME, resourceDummyOrange); dummyResourceCtlOrange.extendSchemaPirate(); dummyResourceOrange = dummyResourceCtlOrange.getDummyResource(); resourceDummyOrange = importAndGetObjectFromFile( ResourceType.class, RESOURCE_DUMMY_ORANGE_FILENAME, RESOURCE_DUMMY_ORANGE_OID, initTask, initResult); resourceDummyOrangeType = resourceDummyOrange.asObjectable(); dummyResourceCtlOrange.setResource(resourceDummyOrange); dummyResourceCtlUpcase = DummyResourceContoller.create(RESOURCE_DUMMY_UPCASE_NAME, resourceDummyUpcase); dummyResourceCtlUpcase.extendSchemaPirate(); dummyResourceUpcase = dummyResourceCtlUpcase.getDummyResource(); resourceDummyUpcase = importAndGetObjectFromFile( ResourceType.class, RESOURCE_DUMMY_UPCASE_FILE, RESOURCE_DUMMY_UPCASE_OID, initTask, initResult); resourceDummyUpcaseType = resourceDummyUpcase.asObjectable(); dummyResourceCtlUpcase.setResource(resourceDummyUpcase); dummyResourceCtlUpcase.addGroup(GROUP_JOKER_DUMMY_UPCASE_NAME); resourceDummySchemaless = importAndGetObjectFromFile( ResourceType.class, RESOURCE_DUMMY_SCHEMALESS_FILENAME, RESOURCE_DUMMY_SCHEMALESS_OID, initTask, initResult); resourceDummySchemalessType = resourceDummySchemaless.asObjectable(); postInitDummyResouce(); dummyResourceCtl.addAccount(ACCOUNT_HERMAN_DUMMY_USERNAME, "Herman Toothrot", "Monkey Island"); dummyResourceCtl.addAccount( ACCOUNT_GUYBRUSH_DUMMY_USERNAME, "Guybrush Threepwood", "Melee Island"); dummyResourceCtl.addAccount( ACCOUNT_DAVIEJONES_DUMMY_USERNAME, "Davie Jones", "Davie Jones' Locker"); dummyResourceCtl.addAccount(ACCOUNT_CALYPSO_DUMMY_USERNAME, "Tia Dalma", "Pantano River"); dummyResourceCtl.addAccount(ACCOUNT_ELAINE_DUMMY_USERNAME, "Elaine Marley", "Melee Island"); dummyResourceCtlRed.addAccount(ACCOUNT_ELAINE_DUMMY_USERNAME, "Elaine Marley", "Melee Island"); dummyResourceCtlBlue.addAccount(ACCOUNT_ELAINE_DUMMY_USERNAME, "Elaine Marley", "Melee Island"); repoAddObjectFromFile(LOOKUP_LANGUAGES_FILE, ObjectTemplateType.class, initResult); repoAddObjectFromFile(SECURITY_POLICY_FILE, SecurityPolicyType.class, initResult); // User Templates repoAddObjectFromFile(USER_TEMPLATE_FILENAME, ObjectTemplateType.class, initResult); repoAddObjectFromFile(USER_TEMPLATE_COMPLEX_FILENAME, ObjectTemplateType.class, initResult); repoAddObjectFromFile( USER_TEMPLATE_COMPLEX_INCLUDE_FILENAME, ObjectTemplateType.class, initResult); repoAddObjectFromFile( USER_TEMPLATE_ORG_ASSIGNMENT_FILENAME, ObjectTemplateType.class, initResult); // Shadows repoAddObjectFromFile(ACCOUNT_SHADOW_GUYBRUSH_DUMMY_FILE, ShadowType.class, initResult); repoAddObjectFromFile(ACCOUNT_SHADOW_ELAINE_DUMMY_FILE, ShadowType.class, initResult); repoAddObjectFromFile(ACCOUNT_SHADOW_ELAINE_DUMMY_RED_FILE, ShadowType.class, initResult); repoAddObjectFromFile(ACCOUNT_SHADOW_ELAINE_DUMMY_BLUE_FILE, ShadowType.class, initResult); repoAddObjectFromFile(GROUP_SHADOW_JOKER_DUMMY_UPCASE_FILE, ShadowType.class, initResult); // Users userTypeJack = repoAddObjectFromFile(USER_JACK_FILE, UserType.class, true, initResult).asObjectable(); userTypeBarbossa = repoAddObjectFromFile(USER_BARBOSSA_FILE, UserType.class, initResult).asObjectable(); userTypeGuybrush = repoAddObjectFromFile(USER_GUYBRUSH_FILE, UserType.class, initResult).asObjectable(); userTypeElaine = repoAddObjectFromFile(USER_ELAINE_FILENAME, UserType.class, initResult).asObjectable(); // Roles repoAddObjectFromFile(ROLE_PIRATE_FILE, RoleType.class, initResult); repoAddObjectFromFile(ROLE_NICE_PIRATE_FILENAME, RoleType.class, initResult); repoAddObjectFromFile(ROLE_CAPTAIN_FILENAME, RoleType.class, initResult); repoAddObjectFromFile(ROLE_JUDGE_FILE, RoleType.class, initResult); repoAddObjectFromFile(ROLE_JUDGE_DEPRECATED_FILE, RoleType.class, initResult); repoAddObjectFromFile(ROLE_THIEF_FILE, RoleType.class, initResult); repoAddObjectFromFile(ROLE_EMPTY_FILE, RoleType.class, initResult); repoAddObjectFromFile(ROLE_SAILOR_FILE, RoleType.class, initResult); // Orgstruct if (doAddOrgstruct()) { repoAddObjectsFromFile(ORG_MONKEY_ISLAND_FILE, OrgType.class, initResult); } } protected boolean doAddOrgstruct() { return true; } protected File getResourceDummyFile() { return RESOURCE_DUMMY_FILE; } protected File getResourceDummyBlueFile() { return RESOURCE_DUMMY_BLUE_FILE; } protected File getResourceDummyGreenFile() { return RESOURCE_DUMMY_GREEN_FILE; } protected void postInitDummyResouce() { // Do nothing be default. Concrete tests may override this. } protected void assertUserJack(PrismObject<UserType> user) { assertUserJack(user, USER_JACK_FULL_NAME, USER_JACK_GIVEN_NAME, USER_JACK_FAMILY_NAME); } protected void assertUserJack(PrismObject<UserType> user, String fullName) { assertUserJack(user, fullName, USER_JACK_GIVEN_NAME, USER_JACK_FAMILY_NAME); } protected void assertUserJack( PrismObject<UserType> user, String fullName, String givenName, String familyName) { assertUserJack(user, fullName, givenName, familyName, "Caribbean"); } protected void assertUserJack( PrismObject<UserType> user, String name, String fullName, String givenName, String familyName, String locality) { assertUser(user, USER_JACK_OID, name, fullName, givenName, familyName, locality); UserType userType = user.asObjectable(); PrismAsserts.assertEqualsPolyString( "Wrong jack honorificPrefix", "Cpt.", userType.getHonorificPrefix()); PrismAsserts.assertEqualsPolyString( "Wrong jack honorificSuffix", "PhD.", userType.getHonorificSuffix()); assertEquals( "Wrong jack emailAddress", "*****@*****.**", userType.getEmailAddress()); assertEquals("Wrong jack telephoneNumber", "555-1234", userType.getTelephoneNumber()); assertEquals("Wrong jack employeeNumber", "emp1234", userType.getEmployeeNumber()); assertEquals("Wrong jack employeeType", "CAPTAIN", userType.getEmployeeType().get(0)); if (locality == null) { assertNull("Locality sneaked to user jack", userType.getLocality()); } else { PrismAsserts.assertEqualsPolyString("Wrong jack locality", locality, userType.getLocality()); } } protected void assertUserJack( PrismObject<UserType> user, String fullName, String givenName, String familyName, String locality) { assertUserJack(user, USER_JACK_USERNAME, fullName, givenName, familyName, locality); } protected void assertDummyAccountShadowRepo( PrismObject<ShadowType> accountShadow, String oid, String username) throws SchemaException { assertAccountShadowRepo(accountShadow, oid, username, resourceDummyType); } protected void assertDummyGroupShadowRepo( PrismObject<ShadowType> accountShadow, String oid, String username) throws SchemaException { assertShadowRepo( accountShadow, oid, username, resourceDummyType, getGroupObjectClass(resourceDummyType)); } protected void assertDummyAccountShadowModel( PrismObject<ShadowType> accountShadow, String oid, String username) throws SchemaException { assertShadowModel( accountShadow, oid, username, resourceDummyType, getAccountObjectClass(resourceDummyType)); } protected void assertDummyGroupShadowModel( PrismObject<ShadowType> accountShadow, String oid, String username) throws SchemaException { assertShadowModel( accountShadow, oid, username, resourceDummyType, getGroupObjectClass(resourceDummyType)); } protected void assertDummyAccountShadowModel( PrismObject<ShadowType> accountShadow, String oid, String username, String fullname) throws SchemaException { assertDummyAccountShadowModel(accountShadow, oid, username); IntegrationTestTools.assertAttribute( accountShadow, dummyResourceCtl.getAttributeFullnameQName(), fullname); } protected void setDefaultUserTemplate(String userTemplateOid) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException { PrismObjectDefinition<SystemConfigurationType> objectDefinition = prismContext .getSchemaRegistry() .findObjectDefinitionByCompileTimeClass(SystemConfigurationType.class); Collection<? extends ItemDelta> modifications; if (userTemplateOid == null) { modifications = ReferenceDelta.createModificationReplaceCollection( SystemConfigurationType.F_DEFAULT_USER_TEMPLATE_REF, objectDefinition, null); } else { PrismReferenceValue userTemplateRefVal = new PrismReferenceValue(userTemplateOid); modifications = ReferenceDelta.createModificationReplaceCollection( SystemConfigurationType.F_DEFAULT_USER_TEMPLATE_REF, objectDefinition, userTemplateRefVal); } OperationResult result = new OperationResult("Aplying default user template"); repositoryService.modifyObject( SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value(), modifications, result); display("Aplying default user template result", result); result.computeStatus(); TestUtil.assertSuccess("Aplying default user template failed (result)", result); } protected void assertMonkeyIslandOrgSanity() throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException { assertMonkeyIslandOrgSanity(0); } protected void assertMonkeyIslandOrgSanity(int expectedFictional) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException { Task task = taskManager.createTaskInstance( AbstractInitializedModelIntegrationTest.class.getName() + ".assertMonkeyIslandOrgSanity"); OperationResult result = task.getResult(); PrismObject<OrgType> orgGovernorOffice = modelService.getObject(OrgType.class, ORG_GOVERNOR_OFFICE_OID, null, task, result); result.computeStatus(); TestUtil.assertSuccess(result); OrgType orgGovernorOfficeType = orgGovernorOffice.asObjectable(); assertEquals( "Wrong governor office name", PrismTestUtil.createPolyStringType("F0001"), orgGovernorOfficeType.getName()); List<PrismObject<OrgType>> governorSubOrgs = searchOrg(ORG_GOVERNOR_OFFICE_OID, OrgFilter.Scope.ONE_LEVEL, task, result); if (verbose) display("governor suborgs", governorSubOrgs); assertEquals("Unexpected number of governor suborgs", 3, governorSubOrgs.size()); List<PrismObject<OrgType>> functionalOrgs = searchOrg(ORG_GOVERNOR_OFFICE_OID, OrgFilter.Scope.SUBTREE, task, result); if (verbose) display("functional orgs (null)", functionalOrgs); assertEquals( "Unexpected number of functional orgs (null)", NUM_FUNCTIONAL_ORGS - 1 + expectedFictional, functionalOrgs.size()); List<PrismObject<OrgType>> prootSubOrgs = searchOrg(ORG_PROJECT_ROOT_OID, OrgFilter.Scope.ONE_LEVEL, task, result); if (verbose) display("project root suborgs", prootSubOrgs); assertEquals("Unexpected number of governor suborgs", 2, prootSubOrgs.size()); List<PrismObject<OrgType>> projectOrgs = searchOrg(ORG_PROJECT_ROOT_OID, OrgFilter.Scope.SUBTREE, task, result); if (verbose) display("project orgs (null)", projectOrgs); assertEquals( "Unexpected number of functional orgs (null)", NUM_PROJECT_ORGS - 1, projectOrgs.size()); PrismObject<OrgType> orgScummBar = modelService.getObject(OrgType.class, ORG_SCUMM_BAR_OID, null, task, result); List<AssignmentType> scummBarInducements = orgScummBar.asObjectable().getInducement(); assertEquals( "Unexpected number of scumm bar inducements: " + scummBarInducements, 1, scummBarInducements.size()); ResultHandler<OrgType> handler = getOrgSanityCheckHandler(); if (handler != null) { modelService.searchObjectsIterative(OrgType.class, null, handler, null, task, result); } } protected ResultHandler<OrgType> getOrgSanityCheckHandler() { return null; } protected void assertShadowOperationalData( PrismObject<ShadowType> shadow, SynchronizationSituationType expectedSituation, Long timeBeforeSync) { ShadowType shadowType = shadow.asObjectable(); SynchronizationSituationType actualSituation = shadowType.getSynchronizationSituation(); assertEquals("Wrong situation in shadow " + shadow, expectedSituation, actualSituation); XMLGregorianCalendar actualTimestampCal = shadowType.getSynchronizationTimestamp(); assert actualTimestampCal != null : "No synchronization timestamp in shadow " + shadow; if (timeBeforeSync != null) { long actualTimestamp = XmlTypeConverter.toMillis(actualTimestampCal); assert actualTimestamp >= timeBeforeSync : "Synchronization timestamp was not updated in shadow " + shadow; } // TODO: assert sync description } }
/** * @author katkav * @author lazyman */ @PageDescriptor( url = "/admin/services", action = { @AuthorizationAction( actionUri = PageAdminServices.AUTH_SERVICES_ALL, label = PageAdminServices.AUTH_SERVICES_ALL_LABEL, description = PageAdminServices.AUTH_SERVICES_ALL_DESCRIPTION), @AuthorizationAction( actionUri = AuthorizationConstants.AUTZ_UI_SERVICES_URL, label = "PageServices.auth.services.label", description = "PageServices.auth.services.description") }) public class PageServices extends PageAdminServices implements FocusListComponent { private static final long serialVersionUID = 1L; private static final String ID_MAIN_FORM = "mainForm"; private static final String ID_TABLE = "table"; private static final String DOT_CLASS = PageServices.class.getName() + "."; private static final Trace LOGGER = TraceManager.getTrace(PageServices.class); private static final String OPERATION_DELETE_SERVICES = DOT_CLASS + "deleteServices"; private IModel<Search> searchModel; public PageServices() { this(true); } public PageServices(boolean clearPagingInSession) { initLayout(); } private final FocusListInlineMenuHelper<ServiceType> listInlineMenuHelper = new FocusListInlineMenuHelper<>(ServiceType.class, this, this); private void initLayout() { Form mainForm = new Form(ID_MAIN_FORM); add(mainForm); MainObjectListPanel<ServiceType> servicePanel = new MainObjectListPanel<ServiceType>( ID_TABLE, ServiceType.class, TableId.TABLE_SERVICES, null, this) { private static final long serialVersionUID = 1L; @Override public void objectDetailsPerformed(AjaxRequestTarget target, ServiceType service) { PageServices.this.serviceDetailsPerformed(target, service); } @Override protected List<IColumn<SelectableBean<ServiceType>, String>> createColumns() { List<IColumn<SelectableBean<ServiceType>, String>> columns = ColumnUtils.getDefaultServiceColumns(); IColumn column = new InlineMenuHeaderColumn(listInlineMenuHelper.initInlineMenu()); columns.add(column); return columns; } @Override protected List<InlineMenuItem> createInlineMenu() { return listInlineMenuHelper.createRowActions(); } @Override protected void newObjectPerformed(AjaxRequestTarget target) { navigateToNext(PageService.class); } }; servicePanel.setAdditionalBoxCssClasses(GuiStyleConstants.CLASS_OBJECT_SERVICE_BOX_CSS_CLASSES); servicePanel.setOutputMarkupId(true); mainForm.add(servicePanel); } protected void serviceDetailsPerformed(AjaxRequestTarget target, ServiceType service) { PageParameters parameters = new PageParameters(); parameters.add(OnePageParameterEncoder.PARAMETER, service.getOid()); navigateToNext(PageService.class, parameters); } @Override public MainObjectListPanel<ServiceType> getObjectListPanel() { return (MainObjectListPanel<ServiceType>) get(createComponentPath(ID_MAIN_FORM, ID_TABLE)); } }
/** @author lazyman */ @PageDescriptor( url = "/admin/resources/content/accounts", encoder = OnePageParameterEncoder.class, action = { @AuthorizationAction( actionUri = PageAdminResources.AUTH_RESOURCE_ALL, label = PageAdminResources.AUTH_RESOURCE_ALL_LABEL, description = PageAdminResources.AUTH_RESOURCE_ALL_DESCRIPTION), @AuthorizationAction( actionUri = AuthorizationConstants.AUTZ_UI_RESOURCES_CONTENT_ACCOUNTS_URL, label = "PageContentAccounts.auth.resourcesContentAccounts.label", description = "PageContentAccounts.auth.resourcesContentAccounts.description") }) public class PageContentAccounts extends PageAdminResources { private static final Trace LOGGER = TraceManager.getTrace(PageContentAccounts.class); private static final String DOT_CLASS = PageContentAccounts.class.getName() + "."; private static final String OPERATION_CHANGE_OWNER = DOT_CLASS + "changeOwner"; private static final String OPERATION_CREATE_USER_FROM_ACCOUNTS = DOT_CLASS + "createUserFromAccounts"; private static final String OPERATION_CREATE_USER_FROM_ACCOUNT = DOT_CLASS + "createUserFromAccount"; private static final String OPERATION_DELETE_ACCOUNT_FROM_RESOURCE = DOT_CLASS + "deleteAccountFromResource"; private static final String OPERATION_ADJUST_ACCOUNT_STATUS = "changeAccountActivationStatus"; private static final String MODAL_ID_OWNER_CHANGE = "ownerChangePopup"; private static final String MODAL_ID_CONFIRM_DELETE = "confirmDeletePopup"; private static final String ID_MAIN_FORM = "mainForm"; private static final String ID_BASIC_SEARCH = "basicSearch"; private static final String ID_SEARCH_FORM = "searchForm"; private static final String ID_NAME_CHECK = "nameCheck"; private static final String ID_IDENTIFIERS_CHECK = "identifiersCheck"; private static final String ID_TABLE = "table"; private IModel<PrismObject<ResourceType>> resourceModel; private IModel<AccountContentSearchDto> searchModel; private LoadableModel<AccountOwnerChangeDto> ownerChangeModel; private AccountContentDto singleDelete; public PageContentAccounts() { searchModel = new LoadableModel<AccountContentSearchDto>() { @Override protected AccountContentSearchDto load() { ResourcesStorage storage = getSessionStorage().getResources(); AccountContentSearchDto dto = storage.getAccountContentSearch(); if (dto == null) { dto = new AccountContentSearchDto(); } return dto; } }; resourceModel = new LoadableModel<PrismObject<ResourceType>>(false) { @Override protected PrismObject<ResourceType> load() { if (!isResourceOidAvailable()) { getSession().error(getString("pageContentAccounts.message.resourceOidNotDefined")); throw new RestartResponseException(PageResources.class); } return loadResource(null); } }; ownerChangeModel = new LoadableModel<AccountOwnerChangeDto>(false) { @Override protected AccountOwnerChangeDto load() { return new AccountOwnerChangeDto(); } }; initLayout(); } private void initDialog() { UserBrowserDialog<UserType> dialog = new UserBrowserDialog<UserType>(MODAL_ID_OWNER_CHANGE, UserType.class) { @Override public void userDetailsPerformed(AjaxRequestTarget target, UserType user) { super.userDetailsPerformed(target, user); ownerChangePerformed(target, user); target.add(getTable()); } }; add(dialog); add( new ConfirmationDialog( MODAL_ID_CONFIRM_DELETE, createStringResource("pageContentAccounts.dialog.title.confirmDelete"), createDeleteConfirmString()) { @Override public void yesPerformed(AjaxRequestTarget target) { close(target); deleteConfirmedPerformed(target); } }); } private IModel<String> createDeleteConfirmString() { return new AbstractReadOnlyModel<String>() { @Override public String getObject() { if (singleDelete == null) { return createStringResource( "pageContentAccounts.message.deleteConfirmation", getSelectedAccounts(null).size()) .getString(); } else { return createStringResource( "pageContentAccounts.message.deleteConfirmationSingle", singleDelete.getAccountName()) .getString(); } } }; } private void initLayout() { Form searchForm = new Form(ID_SEARCH_FORM); add(searchForm); CheckBox nameCheck = new CheckBox(ID_NAME_CHECK, new PropertyModel(searchModel, AccountContentSearchDto.F_NAME)); searchForm.add(nameCheck); CheckBox identifiersCheck = new CheckBox( ID_IDENTIFIERS_CHECK, new PropertyModel(searchModel, AccountContentSearchDto.F_IDENTIFIERS)); searchForm.add(identifiersCheck); BasicSearchPanel<AccountContentSearchDto> basicSearch = new BasicSearchPanel<AccountContentSearchDto>(ID_BASIC_SEARCH) { @Override protected IModel<String> createSearchTextModel() { return new PropertyModel<>(searchModel, AccountContentSearchDto.F_SEARCH_TEXT); } @Override protected void searchPerformed(AjaxRequestTarget target) { PageContentAccounts.this.searchPerformed(target); } @Override protected void clearSearchPerformed(AjaxRequestTarget target) { PageContentAccounts.this.clearSearchPerformed(target); } }; searchForm.add(basicSearch); Form mainForm = new Form(ID_MAIN_FORM); add(mainForm); AccountContentDataProvider provider = new AccountContentDataProvider( this, new PropertyModel<String>(resourceModel, "oid"), createObjectClassModel(), createUseObjectCountingModel()) { @Override protected void addInlineMenuToDto(AccountContentDto dto) { addRowMenuToTable(dto); } }; provider.setQuery(createQuery()); List<IColumn> columns = initColumns(); TablePanel table = new TablePanel( ID_TABLE, provider, columns, UserProfileStorage.TableId.PAGE_RESOURCE_ACCOUNTS_PANEL, getItemsPerPage(UserProfileStorage.TableId.PAGE_RESOURCE_ACCOUNTS_PANEL)); table.setOutputMarkupId(true); mainForm.add(table); initDialog(); } private List<IColumn> initColumns() { List<IColumn> columns = new ArrayList<IColumn>(); IColumn column = new CheckBoxColumn(new Model<String>(), AccountContentDto.F_SELECTED); columns.add(column); column = new LinkColumn<AccountContentDto>( createStringResource("pageContentAccounts.name"), AccountContentDto.F_ACCOUNT_NAME) { @Override public void onClick(AjaxRequestTarget target, IModel<AccountContentDto> rowModel) { AccountContentDto dto = rowModel.getObject(); accountDetailsPerformed(target, dto.getAccountName(), dto.getAccountOid()); } }; columns.add(column); column = new AbstractColumn<AccountContentDto, String>( createStringResource("pageContentAccounts.identifiers")) { @Override public void populateItem( Item<ICellPopulator<AccountContentDto>> cellItem, String componentId, IModel<AccountContentDto> rowModel) { AccountContentDto dto = rowModel.getObject(); List values = new ArrayList(); for (ResourceAttribute<?> attr : dto.getIdentifiers()) { values.add(attr.getElementName().getLocalPart() + ": " + attr.getRealValue()); } cellItem.add(new Label(componentId, new Model<>(StringUtils.join(values, ", ")))); } }; columns.add(column); column = new PropertyColumn( createStringResource("pageContentAccounts.kind"), AccountContentDto.F_KIND); columns.add(column); column = new PropertyColumn( createStringResource("pageContentAccounts.intent"), AccountContentDto.F_INTENT); columns.add(column); column = new PropertyColumn( createStringResource("pageContentAccounts.objectClass"), AccountContentDto.F_OBJECT_CLASS); columns.add(column); column = new EnumPropertyColumn( createStringResource("pageContentAccounts.situation"), AccountContentDto.F_SITUATION) { @Override protected String translate(Enum en) { return createStringResource(en).getString(); } }; columns.add(column); column = new LinkColumn<AccountContentDto>(createStringResource("pageContentAccounts.owner")) { @Override protected IModel<String> createLinkModel(final IModel<AccountContentDto> rowModel) { return new AbstractReadOnlyModel<String>() { @Override public String getObject() { AccountContentDto dto = rowModel.getObject(); if (StringUtils.isNotBlank(dto.getOwnerName())) { return dto.getOwnerName(); } return dto.getOwnerOid(); } }; } @Override public void onClick(AjaxRequestTarget target, IModel<AccountContentDto> rowModel) { AccountContentDto dto = rowModel.getObject(); ownerDetailsPerformed(target, dto.getOwnerName(), dto.getOwnerOid()); } }; columns.add(column); column = new InlineMenuHeaderColumn(createHeaderMenuItems()); columns.add(column); return columns; } private List<InlineMenuItem> createHeaderMenuItems() { List<InlineMenuItem> items = new ArrayList<InlineMenuItem>(); items.add( new InlineMenuItem( createStringResource("pageContentAccounts.menu.enableAccount"), true, new HeaderMenuAction(this) { @Override public void onSubmit(AjaxRequestTarget target, Form<?> form) { updateAccountStatusPerformed(target, null, true); } })); items.add( new InlineMenuItem( createStringResource("pageContentAccounts.menu.disableAccount"), true, new HeaderMenuAction(this) { @Override public void onSubmit(AjaxRequestTarget target, Form<?> form) { updateAccountStatusPerformed(target, null, false); } })); items.add( new InlineMenuItem( createStringResource("pageContentAccounts.menu.deleteAccount"), true, new HeaderMenuAction(this) { @Override public void onSubmit(AjaxRequestTarget target, Form<?> form) { deleteAccountPerformed(target, null); } })); items.add(new InlineMenuItem()); items.add( new InlineMenuItem( createStringResource("pageContentAccounts.menu.importAccount"), true, new HeaderMenuAction(this) { @Override public void onSubmit(AjaxRequestTarget target, Form<?> form) { importAccount(target, null); } })); items.add(new InlineMenuItem()); items.add( new InlineMenuItem( createStringResource("pageContentAccounts.menu.removeOwner"), true, new HeaderMenuAction(this) { @Override public void onSubmit(AjaxRequestTarget target, Form<?> form) { removeOwnerPerformed(target, null); } })); return items; } private void addRowMenuToTable(final AccountContentDto dto) { dto.getMenuItems() .add( new InlineMenuItem( createStringResource("pageContentAccounts.menu.enableAccount"), true, new HeaderMenuAction(this) { @Override public void onSubmit(AjaxRequestTarget target, Form<?> form) { updateAccountStatusPerformed(target, dto, true); } })); dto.getMenuItems() .add( new InlineMenuItem( createStringResource("pageContentAccounts.menu.disableAccount"), true, new HeaderMenuAction(this) { @Override public void onSubmit(AjaxRequestTarget target, Form<?> form) { updateAccountStatusPerformed(target, dto, false); } })); dto.getMenuItems() .add( new InlineMenuItem( createStringResource("pageContentAccounts.menu.deleteAccount"), true, new HeaderMenuAction(this) { @Override public void onSubmit(AjaxRequestTarget target, Form<?> form) { deleteAccountPerformed(target, dto); } })); dto.getMenuItems().add(new InlineMenuItem()); dto.getMenuItems() .add( new InlineMenuItem( createStringResource("pageContentAccounts.menu.importAccount"), new ColumnMenuAction<UserListItemDto>() { @Override public void onClick(AjaxRequestTarget target) { importAccount(target, dto); } })); dto.getMenuItems().add(new InlineMenuItem()); dto.getMenuItems() .add( new InlineMenuItem( createStringResource("pageContentAccounts.menu.changeOwner"), new ColumnMenuAction<UserListItemDto>() { @Override public void onClick(AjaxRequestTarget target) { changeOwnerPerformed(target, dto); } })); dto.getMenuItems() .add( new InlineMenuItem( createStringResource("pageContentAccounts.menu.removeOwner"), true, new HeaderMenuAction(this) { @Override public void onSubmit(AjaxRequestTarget target, Form<?> form) { removeOwnerPerformed(target, dto); } })); } @Override protected IModel<String> createPageSubTitleModel() { return new LoadableModel<String>(false) { @Override protected String load() { String name = WebMiscUtil.getName(resourceModel.getObject()); return new StringResourceModel( "PageContentAccounts.subTitle", PageContentAccounts.this, null, null, name) .getString(); } }; } private void ownerDetailsPerformed(AjaxRequestTarget target, String ownerName, String ownerOid) { if (StringUtils.isEmpty(ownerOid)) { error(getString("pageContentAccounts.message.cantShowUserDetails", ownerName, ownerOid)); target.add(getFeedbackPanel()); return; } PageParameters parameters = new PageParameters(); parameters.add(OnePageParameterEncoder.PARAMETER, ownerOid); setResponsePage(PageUser.class, parameters); } private void changeOwnerPerformed(AjaxRequestTarget target, AccountContentDto dto) { reloadOwnerChangeModel(dto.getAccountOid(), dto.getOwnerOid()); showModalWindow(MODAL_ID_OWNER_CHANGE, target); } private void reloadOwnerChangeModel(String accountOid, String ownerOid) { ownerChangeModel.reset(); AccountOwnerChangeDto changeDto = ownerChangeModel.getObject(); changeDto.setAccountOid(accountOid); changeDto.setAccountType(ShadowType.COMPLEX_TYPE); changeDto.setOldOwnerOid(ownerOid); } private void importAccount(AjaxRequestTarget target, AccountContentDto row) { List<AccountContentDto> accounts = isAnythingSelected(target, row); if (accounts.isEmpty()) { return; } OperationResult result = new OperationResult(OPERATION_CREATE_USER_FROM_ACCOUNTS); for (AccountContentDto dto : accounts) { OperationResult subResult = result.createMinorSubresult(OPERATION_CREATE_USER_FROM_ACCOUNT); try { getModelService() .importFromResource( dto.getAccountOid(), createSimpleTask(OPERATION_CREATE_USER_FROM_ACCOUNT), subResult); } catch (Exception ex) { subResult.computeStatus( getString("pageContentAccounts.message.cantImportAccount", dto.getAccountOid())); LoggingUtils.logException( LOGGER, "Can't import account {},oid={}", ex, dto.getAccountName(), dto.getAccountOid()); } finally { subResult.computeStatusIfUnknown(); } } result.computeStatus(); showResult(result); target.add(getFeedbackPanel()); target.add(getTable()); } private TablePanel getTable() { return (TablePanel) get(createComponentPath(ID_MAIN_FORM, ID_TABLE)); } private void searchPerformed(AjaxRequestTarget target) { ObjectQuery query = createQuery(); TablePanel panel = getTable(); DataTable table = panel.getDataTable(); AccountContentDataProvider provider = (AccountContentDataProvider) table.getDataProvider(); provider.setQuery(query); table.setCurrentPage(0); target.add(panel); target.add(getFeedbackPanel()); } private ObjectQuery createQuery() { AccountContentSearchDto dto = searchModel.getObject(); if (StringUtils.isEmpty(dto.getSearchText())) { return null; } try { ObjectQuery query = null; List<ObjectFilter> conditions = new ArrayList<>(); ObjectClassComplexTypeDefinition def = getAccountDefinition(); if (dto.isIdentifiers()) { List<ResourceAttributeDefinition> identifiers = new ArrayList<>(); if (def.getIdentifiers() != null) { identifiers.addAll(def.getIdentifiers()); } // TODO set matching rule instead fo null for (ResourceAttributeDefinition attrDef : identifiers) { conditions.add( EqualFilter.createEqual( new ItemPath(ShadowType.F_ATTRIBUTES, attrDef.getName()), attrDef, dto.getSearchText())); } } if (dto.isName()) { List<ResourceAttributeDefinition> secondaryIdentifiers = new ArrayList<>(); if (def.getNamingAttribute() != null) { secondaryIdentifiers.add(def.getNamingAttribute()); } else if (def.getSecondaryIdentifiers() != null) { secondaryIdentifiers.addAll(def.getSecondaryIdentifiers()); } for (ResourceAttributeDefinition attrDef : secondaryIdentifiers) { conditions.add( SubstringFilter.createSubstring( new ItemPath(ShadowType.F_ATTRIBUTES, attrDef.getName()), attrDef, dto.getSearchText())); } } if (!conditions.isEmpty()) { if (conditions.size() > 1) { query = ObjectQuery.createObjectQuery(OrFilter.createOr(conditions)); } else { query = ObjectQuery.createObjectQuery(conditions.get(0)); } } return query; } catch (Exception ex) { error(getString("pageUsers.message.queryError") + " " + ex.getMessage()); LoggingUtils.logException(LOGGER, "Couldn't create query filter.", ex); } return null; } private IModel<QName> createObjectClassModel() { return new LoadableModel<QName>(false) { @Override protected QName load() { try { return getObjectClassDefinition(); } catch (Exception ex) { throw new SystemException(ex.getMessage(), ex); } } }; } private IModel<Boolean> createUseObjectCountingModel() { return new LoadableModel<Boolean>(false) { @Override protected Boolean load() { try { return isUseObjectCounting(); } catch (Exception ex) { throw new SystemException(ex.getMessage(), ex); } } }; } private QName getObjectClassDefinition() throws SchemaException { ObjectClassComplexTypeDefinition def = getAccountDefinition(); return def != null ? def.getTypeName() : null; } private ObjectClassComplexTypeDefinition getAccountDefinition() throws SchemaException { MidPointApplication application = (MidPointApplication) getApplication(); PrismObject<ResourceType> resource = resourceModel.getObject(); RefinedResourceSchema refinedSchema = RefinedResourceSchema.getRefinedSchema(resource, application.getPrismContext()); ObjectClassComplexTypeDefinition def = refinedSchema.findDefaultObjectClassDefinition(ShadowKindType.ACCOUNT); return def; } private boolean isUseObjectCounting() throws SchemaException { MidPointApplication application = (MidPointApplication) getApplication(); PrismObject<ResourceType> resource = resourceModel.getObject(); RefinedResourceSchema resourceSchema = RefinedResourceSchema.getRefinedSchema(resource, application.getPrismContext()); // hacking this for now ... in future, we get the type definition (and maybe kind+intent) // directly from GUI model // TODO here we should deal with the situation that one object class is mentioned in different // kind/intent sections -- we would want to avoid mentioning paged search information in all // these sections ObjectClassComplexTypeDefinition typeDefinition = getAccountDefinition(); if (typeDefinition == null) { // should not occur LOGGER.warn("ObjectClass definition couldn't be found"); return false; } RefinedObjectClassDefinition refinedObjectClassDefinition = resourceSchema.getRefinedDefinition(typeDefinition.getTypeName()); if (refinedObjectClassDefinition == null) { return false; } return refinedObjectClassDefinition.isObjectCountingEnabled(); } private void showModalWindow(String id, AjaxRequestTarget target) { ModalWindow window = (ModalWindow) get(id); window.show(target); } private void accountDetailsPerformed( AjaxRequestTarget target, String accountName, String accountOid) { if (StringUtils.isEmpty(accountOid)) { error( getString("pageContentAccounts.message.cantShowAccountDetails", accountName, accountOid)); target.add(getFeedbackPanel()); return; } PageParameters parameters = new PageParameters(); parameters.add(OnePageParameterEncoder.PARAMETER, accountOid); setResponsePage(PageAccount.class, parameters); } private List<AccountContentDto> getSelectedAccounts(AccountContentDto dto) { List<AccountContentDto> accounts; if (dto != null) { accounts = new ArrayList<>(); accounts.add(dto); } else { accounts = WebMiscUtil.getSelectedData(getTable()); } return accounts; } private List<AccountContentDto> isAnythingSelected( AjaxRequestTarget target, AccountContentDto dto) { List<AccountContentDto> accounts; if (dto != null) { accounts = new ArrayList<>(); accounts.add(dto); } else { accounts = WebMiscUtil.getSelectedData(getTable()); if (accounts.isEmpty()) { warn(getString("pageContentAccounts.message.noAccountSelected")); target.add(getFeedbackPanel()); } } return accounts; } private void removeOwnerPerformed(AjaxRequestTarget target, AccountContentDto row) { List<AccountContentDto> accounts = isAnythingSelected(target, row); if (accounts.isEmpty()) { return; } for (AccountContentDto dto : accounts) { reloadOwnerChangeModel(dto.getAccountOid(), dto.getOwnerOid()); ownerChangePerformed(target, null); } target.add(getTable()); target.add(getFeedbackPanel()); } private void ownerChangePerformed(AjaxRequestTarget target, UserType user) { AccountOwnerChangeDto dto = ownerChangeModel.getObject(); OperationResult result = new OperationResult(OPERATION_CHANGE_OWNER); try { Task task = createSimpleTask(OPERATION_CHANGE_OWNER); if (StringUtils.isNotEmpty(dto.getOldOwnerOid())) { ObjectDelta delta = new ObjectDelta(UserType.class, ChangeType.MODIFY, getPrismContext()); delta.setOid(dto.getOldOwnerOid()); PrismReferenceValue refValue = new PrismReferenceValue(dto.getAccountOid()); refValue.setTargetType(dto.getAccountType()); delta.addModification( ReferenceDelta.createModificationDelete( UserType.class, UserType.F_LINK_REF, getPrismContext(), refValue)); getModelService() .executeChanges(WebMiscUtil.createDeltaCollection(delta), null, task, result); } if (user != null) { ObjectDelta delta = new ObjectDelta(UserType.class, ChangeType.MODIFY, getPrismContext()); delta.setOid(user.getOid()); PrismReferenceValue refValue = new PrismReferenceValue(dto.getAccountOid()); refValue.setTargetType(dto.getAccountType()); delta.addModification( ReferenceDelta.createModificationAdd( UserType.class, UserType.F_LINK_REF, getPrismContext(), refValue)); getModelService() .executeChanges(WebMiscUtil.createDeltaCollection(delta), null, task, result); } result.recomputeStatus(); } catch (Exception ex) { result.recordFatalError("Couldn't submit user.", ex); LoggingUtils.logException(LOGGER, "Couldn't submit user", ex); } showResult(result); target.add(getFeedbackPanel()); } private void clearSearchPerformed(AjaxRequestTarget target) { searchModel.setObject(new AccountContentSearchDto()); TablePanel panel = getTable(); DataTable table = panel.getDataTable(); AccountContentDataProvider provider = (AccountContentDataProvider) table.getDataProvider(); provider.setQuery(null); ResourcesStorage storage = getSessionStorage().getResources(); storage.setAccountContentSearch(searchModel.getObject()); storage.setAccountContentPaging(null); panel.setCurrentPage(null); target.add(get(ID_SEARCH_FORM)); target.add(panel); } private void deleteAccountPerformed(AjaxRequestTarget target, AccountContentDto dto) { singleDelete = dto; List<AccountContentDto> accounts = isAnythingSelected(target, dto); if (accounts.isEmpty()) { return; } showModalWindow(MODAL_ID_CONFIRM_DELETE, target); } private void deleteConfirmedPerformed(AjaxRequestTarget target) { List<AccountContentDto> selected = new ArrayList<AccountContentDto>(); if (singleDelete != null) { selected.add(singleDelete); } else { selected = isAnythingSelected(target, null); } OperationResult result = new OperationResult(OPERATION_DELETE_ACCOUNT_FROM_RESOURCE); for (AccountContentDto acc : selected) { String accOid = acc.getAccountOid(); try { Task task = createSimpleTask(OPERATION_DELETE_ACCOUNT_FROM_RESOURCE); ObjectDelta delta = ObjectDelta.createDeleteDelta(ShadowType.class, accOid, getPrismContext()); getModelService() .executeChanges(WebMiscUtil.createDeltaCollection(delta), null, task, result); } catch (Exception e) { result.recordPartialError("Couldn't delete account from resource.", e); LoggingUtils.logException(LOGGER, "Couldn't delete account from resource", e); } } if (result.isUnknown()) { result.recomputeStatus("Error occurred during resource account deletion."); } if (result.isSuccess()) { result.recordStatus( OperationResultStatus.SUCCESS, "Selected accounts have been successfully deleted."); } AccountContentDataProvider provider = (AccountContentDataProvider) getTable().getDataTable().getDataProvider(); provider.clearCache(); TablePanel table = getTable(); target.add(table); showResult(result); target.add(getFeedbackPanel()); } private void updateAccountStatusPerformed( AjaxRequestTarget target, AccountContentDto dto, boolean enabled) { List<AccountContentDto> accounts = isAnythingSelected(target, dto); OperationResult result = new OperationResult(OPERATION_ADJUST_ACCOUNT_STATUS); if (accounts.isEmpty()) { return; } ActivationStatusType status = enabled ? ActivationStatusType.ENABLED : ActivationStatusType.DISABLED; for (AccountContentDto acc : accounts) { ObjectDelta delta = ObjectDelta.createModificationReplaceProperty( ShadowType.class, acc.getAccountOid(), new ItemPath(ShadowType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS), getPrismContext(), status); try { Task task = createSimpleTask(OPERATION_ADJUST_ACCOUNT_STATUS); getModelService() .executeChanges(WebMiscUtil.createDeltaCollection(delta), null, task, result); } catch (Exception e) { LoggingUtils.logException(LOGGER, "Couldn't enable/disable account(s) on resource", e); result.recordPartialError("Couldn't enable/disable account(s) on resource", e); } } result.recomputeStatus(); showResult(result); target.add(getFeedbackPanel()); } }
/** @author lazyman */ @PageDescriptor( url = "/admin/reports/created", action = { @AuthorizationAction( actionUri = PageAdminReports.AUTH_REPORTS_ALL, label = PageAdminConfiguration.AUTH_CONFIGURATION_ALL_LABEL, description = PageAdminConfiguration.AUTH_CONFIGURATION_ALL_DESCRIPTION), @AuthorizationAction( actionUri = AuthorizationConstants.AUTZ_UI_REPORTS_CREATED_REPORTS_URL, label = "PageCreatedReports.auth.createdReports.label", description = "PageCreatedReports.auth.createdReports.description") }) public class PageCreatedReports extends PageAdminReports { private static final Trace LOGGER = TraceManager.getTrace(PageCreatedReports.class); private static final String DOT_CLASS = PageCreatedReports.class.getName() + "."; private static final String OPERATION_DELETE = DOT_CLASS + "deleteReportOutput"; private static final String OPERATION_DOWNLOAD_REPORT = DOT_CLASS + "downloadReport"; private static final String ID_MAIN_FORM = "mainForm"; private static final String ID_CREATED_REPORTS_TABLE = "table"; private static final String ID_SEARCH_FORM = "searchForm"; private static final String ID_BASIC_SEARCH = "basicSearch"; private static final String ID_FILTER_FILE_TYPE = "filetype"; private static final String ID_REPORT_TYPE_SELECT = "reportType"; private static final String ID_CONFIRM_DELETE = "confirmDeletePopup"; private static final String ID_TABLE_HEADER = "tableHeader"; private LoadableModel<ReportOutputSearchDto> searchModel; private IModel<ReportDeleteDialogDto> deleteModel = new Model<>(); private ReportOutputType currentReport; private static Map<ExportType, String> reportExportTypeMap = new HashMap<>(); static { reportExportTypeMap.put(ExportType.CSV, "text/csv; charset=UTF-8"); reportExportTypeMap.put( ExportType.DOCX, "application/vnd.openxmlformats-officedocument.wordprocessingml.document; charset=UTF-8"); reportExportTypeMap.put(ExportType.HTML, "text/html; charset=UTF-8"); reportExportTypeMap.put( ExportType.ODS, "application/vnd.oasis.opendocument.spreadsheet; charset=UTF-8"); reportExportTypeMap.put( ExportType.ODT, "application/vnd.oasis.opendocument.text; charset=UTF-8"); reportExportTypeMap.put(ExportType.PDF, "application/pdf; charset=UTF-8"); reportExportTypeMap.put( ExportType.PPTX, "application/vnd.openxmlformats-officedocument.presentationml.presentation; charset=UTF-8"); reportExportTypeMap.put(ExportType.RTF, "application/rtf; charset=UTF-8"); reportExportTypeMap.put(ExportType.XHTML, "application/xhtml+xml; charset=UTF-8"); reportExportTypeMap.put(ExportType.XLS, "application/vnd.ms-excel; charset=UTF-8"); reportExportTypeMap.put( ExportType.XLSX, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=UTF-8"); reportExportTypeMap.put(ExportType.XML, "application/xml; charset=UTF-8"); reportExportTypeMap.put(ExportType.XML_EMBED, "text/xml; charset=UTF-8"); } public PageCreatedReports() { this(new PageParameters(), null); } public PageCreatedReports(PageParameters pageParameters, PageBase previousPage) { super(pageParameters); setPreviousPage(previousPage); searchModel = new LoadableModel<ReportOutputSearchDto>(false) { @Override protected ReportOutputSearchDto load() { ReportsStorage storage = getSessionStorage().getReports(); ReportOutputSearchDto dto = storage.getReportOutputSearch(); if (dto != null) { return dto; } return createSearchDto(); } }; initLayout(); } private ReportOutputSearchDto createSearchDto() { ReportOutputSearchDto dto = new ReportOutputSearchDto(); Map<String, String> reportTypeMap = dto.getReportTypeMap(); List<PrismObject<ReportType>> reportTypes = WebModelUtils.searchObjects(ReportType.class, null, null, getPageBase()); LOGGER.debug("Found {} report types.", reportTypes.size()); for (PrismObject o : reportTypes) { ReportType reportType = (ReportType) o.asObjectable(); if (reportType.isParent()) { String name = WebMiscUtil.getName(o); reportTypeMap.put(name, reportType.getOid()); } } StringValue param = getPage().getPageParameters().get(OnePageParameterEncoder.PARAMETER); if (param != null) { for (String key : dto.getReportTypeMap().keySet()) { if (reportTypeMap.get(key).equals(param.toString())) { dto.setReportType(key); } } } return dto; } private void initLayout() { Form mainForm = new Form(ID_MAIN_FORM); add(mainForm); final AjaxDownloadBehaviorFromStream ajaxDownloadBehavior = new AjaxDownloadBehaviorFromStream() { @Override protected InputStream initStream() { if (currentReport != null) { String contentType = reportExportTypeMap.get(currentReport.getExportType()); if (StringUtils.isEmpty(contentType)) { contentType = "multipart/mixed; charset=UTF-8"; } setContentType(contentType); } return createReport(); } }; mainForm.add(ajaxDownloadBehavior); ObjectDataProvider provider = new ObjectDataProvider(PageCreatedReports.this, ReportOutputType.class) { @Override protected void saveProviderPaging(ObjectQuery query, ObjectPaging paging) { ReportsStorage storage = getSessionStorage().getReports(); storage.setReportOutputsPaging(paging); } @Override public ObjectQuery getQuery() { return createQuery(); } }; BoxedTablePanel table = new BoxedTablePanel( ID_CREATED_REPORTS_TABLE, provider, initColumns(ajaxDownloadBehavior), UserProfileStorage.TableId.PAGE_CREATED_REPORTS_PANEL, (int) getItemsPerPage(UserProfileStorage.TableId.PAGE_CREATED_REPORTS_PANEL)) { @Override protected WebMarkupContainer createHeader(String headerId) { return new SearchFragment( headerId, ID_TABLE_HEADER, PageCreatedReports.this, searchModel); } }; table.setShowPaging(true); table.setOutputMarkupId(true); mainForm.add(table); add( new ConfirmationDialog( ID_CONFIRM_DELETE, createStringResource("pageCreatedReports.dialog.title.confirmDelete"), createDeleteConfirmString()) { @Override public void yesPerformed(AjaxRequestTarget target) { close(target); ReportDeleteDialogDto dto = deleteModel.getObject(); switch (dto.getOperation()) { case DELETE_SINGLE: deleteSelectedConfirmedPerformed(target, Arrays.asList(dto.getObjects().get(0))); break; case DELETE_SELECTED: deleteSelectedConfirmedPerformed(target, dto.getObjects()); break; case DELETE_ALL: deleteAllConfirmedPerformed(target); break; } } }); } // TODO - commented until FileType property will be available in ReportOutputType public PageBase getPageBase() { return (PageBase) getPage(); } // TODO - consider adding Author name, File Type and ReportType to columns private List<IColumn<SelectableBean<ReportOutputType>, String>> initColumns( final AjaxDownloadBehaviorFromStream ajaxDownloadBehavior) { List<IColumn<SelectableBean<ReportOutputType>, String>> columns = new ArrayList<>(); IColumn column; column = new CheckBoxHeaderColumn(); columns.add(column); column = new PropertyColumn( createStringResource("pageCreatedReports.table.name"), "name", "value.name"); columns.add(column); column = new PropertyColumn( createStringResource("pageCreatedReports.table.description"), "value.description"); columns.add(column); column = new AbstractColumn<SelectableBean<ReportOutputType>, String>( createStringResource("pageCreatedReports.table.time"), "createTimestamp") { @Override public void populateItem( Item<ICellPopulator<SelectableBean<ReportOutputType>>> cellItem, String componentId, final IModel<SelectableBean<ReportOutputType>> rowModel) { cellItem.add( new Label( componentId, new AbstractReadOnlyModel() { @Override public Object getObject() { ReportOutputType object = rowModel.getObject().getValue(); MetadataType metadata = object.getMetadata(); if (metadata == null) { return null; } return WebMiscUtil.formatDate(metadata.getCreateTimestamp()); } })); } }; columns.add(column); column = new AbstractColumn<SelectableBean<ReportOutputType>, String>(new Model(), null) { @Override public void populateItem( Item<ICellPopulator<SelectableBean<ReportOutputType>>> cellItem, String componentId, final IModel<SelectableBean<ReportOutputType>> model) { DownloadButtonPanel panel = new DownloadButtonPanel(componentId) { @Override protected void deletePerformed(AjaxRequestTarget target) { deleteSelectedPerformed( target, ReportDeleteDialogDto.Operation.DELETE_SINGLE, model.getObject().getValue()); } @Override protected void downloadPerformed(AjaxRequestTarget target) { currentReport = model.getObject().getValue(); PageCreatedReports.this.downloadPerformed( target, model.getObject().getValue(), ajaxDownloadBehavior); } }; cellItem.add(panel); } }; columns.add(column); column = new InlineMenuHeaderColumn<InlineMenuable>(initInlineMenu()) { @Override public void populateItem( Item<ICellPopulator<InlineMenuable>> cellItem, String componentId, IModel<InlineMenuable> rowModel) { cellItem.add(new Label(componentId)); } }; columns.add(column); return columns; } private List<InlineMenuItem> initInlineMenu() { List<InlineMenuItem> headerMenuItems = new ArrayList<>(); headerMenuItems.add( new InlineMenuItem( createStringResource("pageCreatedReports.inlineMenu.deleteAll"), true, new HeaderMenuAction(this) { @Override public void onSubmit(AjaxRequestTarget target, Form<?> form) { deleteAllPerformed(target, ReportDeleteDialogDto.Operation.DELETE_ALL); } })); headerMenuItems.add( new InlineMenuItem( createStringResource("pageCreatedReports.inlineMenu.deleteSelected"), true, new HeaderMenuAction(this) { @Override public void onSubmit(AjaxRequestTarget target, Form<?> form) { deleteSelectedPerformed( target, ReportDeleteDialogDto.Operation.DELETE_SELECTED, null); } })); return headerMenuItems; } private IModel<String> createDeleteConfirmString() { return new AbstractReadOnlyModel<String>() { @Override public String getObject() { ReportDeleteDialogDto dto = deleteModel.getObject(); switch (dto.getOperation()) { case DELETE_SINGLE: ReportOutputType report = dto.getObjects().get(0); return createStringResource( "pageCreatedReports.message.deleteOutputSingle", report.getName().getOrig()) .getString(); case DELETE_ALL: return createStringResource("pageCreatedReports.message.deleteAll").getString(); default: return createStringResource( "pageCreatedReports.message.deleteOutputConfirmed", getSelectedData().size()) .getString(); } } }; } private List<ReportOutputType> getSelectedData() { ObjectDataProvider<SelectableBean<ReportOutputType>, ReportOutputType> provider = getReportDataProvider(); List<SelectableBean<ReportOutputType>> rows = provider.getAvailableData(); List<ReportOutputType> selected = new ArrayList<>(); for (SelectableBean<ReportOutputType> row : rows) { if (row.isSelected()) { selected.add(row.getValue()); } } return selected; } private ObjectDataProvider<SelectableBean<ReportOutputType>, ReportOutputType> getReportDataProvider() { DataTable table = getReportOutputTable().getDataTable(); return (ObjectDataProvider<SelectableBean<ReportOutputType>, ReportOutputType>) table.getDataProvider(); } private Table getReportOutputTable() { return (Table) get(createComponentPath(ID_MAIN_FORM, ID_CREATED_REPORTS_TABLE)); } private ObjectDataProvider getTableDataProvider() { Table tablePanel = getReportOutputTable(); DataTable table = tablePanel.getDataTable(); return (ObjectDataProvider) table.getDataProvider(); } private void deleteAllPerformed(AjaxRequestTarget target, ReportDeleteDialogDto.Operation op) { ReportDeleteDialogDto dto = new ReportDeleteDialogDto(op, null); deleteModel.setObject(dto); ModalWindow dialog = (ModalWindow) get(ID_CONFIRM_DELETE); dialog.show(target); } private void deleteSelectedPerformed( AjaxRequestTarget target, ReportDeleteDialogDto.Operation op, ReportOutputType single) { List<ReportOutputType> selected = getSelectedData(); if (single != null) { selected.clear(); selected.add(single); } if (selected.isEmpty()) { return; } ReportDeleteDialogDto dto = new ReportDeleteDialogDto(op, selected); deleteModel.setObject(dto); ModalWindow dialog = (ModalWindow) get(ID_CONFIRM_DELETE); dialog.show(target); } private void deleteSelectedConfirmedPerformed( AjaxRequestTarget target, List<ReportOutputType> objects) { OperationResult result = new OperationResult(OPERATION_DELETE); for (ReportOutputType output : objects) { WebModelUtils.deleteObject(ReportOutputType.class, output.getOid(), result, this); } result.computeStatusIfUnknown(); ObjectDataProvider provider = getTableDataProvider(); provider.clearCache(); showResult(result); target.add((Component) getReportOutputTable()); target.add(getFeedbackPanel()); } private void deleteAllConfirmedPerformed(AjaxRequestTarget target) { // TODO - implement as background task warn("Not implemented yet, will be implemented as background task."); target.add(getFeedbackPanel()); } private ObjectQuery createQuery() { ReportOutputSearchDto dto = searchModel.getObject(); try { List<ObjectFilter> ands = new ArrayList<>(); if (StringUtils.isNotEmpty(dto.getText())) { PolyStringNormalizer normalizer = getPrismContext().getDefaultPolyStringNormalizer(); String normalizedString = normalizer.normalize(dto.getText()); SubstringFilter substring = SubstringFilter.createSubstring( ReportOutputType.F_NAME, ReportOutputType.class, getPrismContext(), PolyStringNormMatchingRule.NAME, normalizedString); ands.add(substring); } String oid = dto.getReportTypeMap().get(dto.getReportType()); if (StringUtils.isNotEmpty(oid)) { RefFilter ref = RefFilter.createReferenceEqual( ReportOutputType.F_REPORT_REF, ReportOutputType.class, getPrismContext(), oid); ands.add(ref); } switch (ands.size()) { case 0: return null; case 1: return ObjectQuery.createObjectQuery(ands.get(0)); default: AndFilter and = AndFilter.createAnd(ands); return ObjectQuery.createObjectQuery(and); } } catch (Exception e) { error(getString("pageCreatedReports.message.queryError") + " " + e.getMessage()); LoggingUtils.logException(LOGGER, "Couldn't create query filter.", e); return null; } } private InputStream createReport() { OperationResult result = new OperationResult(OPERATION_DOWNLOAD_REPORT); ReportManager reportManager = getReportManager(); if (currentReport == null) { return null; } InputStream input = null; try { input = reportManager.getReportOutputData(currentReport.getOid(), result); } catch (Exception e) { error(getString("pageCreatedReports.message.downloadError") + " " + e.getMessage()); LoggingUtils.logException(LOGGER, "Couldn't download report.", e); LOGGER.trace(result.debugDump()); } finally { result.computeStatusIfUnknown(); } if (WebMiscUtil.showResultInPage(result)) { showResultInSession(result); } return input; } private void fileTypeFilterPerformed(AjaxRequestTarget target) { // TODO - perform filtering based on file type - need to wait for schema update // (ReportOutputType) } private void downloadPerformed( AjaxRequestTarget target, ReportOutputType report, AjaxDownloadBehaviorFromStream ajaxDownloadBehavior) { ajaxDownloadBehavior.initiate(target); } private void searchPerformed(AjaxRequestTarget target) { refreshTable(target); } private void clearSearchPerformed(AjaxRequestTarget target) { ReportOutputSearchDto dto = searchModel.getObject(); dto.setReportType(null); dto.setText(null); refreshTable(target); } private void refreshTable(AjaxRequestTarget target) { Table panel = getReportOutputTable(); ReportsStorage storage = getSessionStorage().getReports(); storage.setReportOutputSearch(searchModel.getObject()); storage.setReportOutputsPaging(null); panel.setCurrentPage(0); target.add((Component) panel); target.add(getFeedbackPanel()); } private static class SearchFragment extends Fragment { public SearchFragment( String id, String markupId, MarkupContainer markupProvider, IModel<ReportOutputSearchDto> model) { super(id, markupId, markupProvider, model); initLayout(); } private void initLayout() { final Form searchForm = new Form(ID_SEARCH_FORM); add(searchForm); searchForm.setOutputMarkupId(true); final IModel<ReportOutputSearchDto> model = (IModel) getDefaultModel(); BasicSearchPanel<ReportOutputSearchDto> basicSearch = new BasicSearchPanel<ReportOutputSearchDto>(ID_BASIC_SEARCH, model) { @Override protected IModel<String> createSearchTextModel() { return new PropertyModel<String>(model, UsersDto.F_TEXT); } @Override protected void searchPerformed(AjaxRequestTarget target) { PageCreatedReports page = (PageCreatedReports) getPage(); page.searchPerformed(target); } @Override protected void clearSearchPerformed(AjaxRequestTarget target) { PageCreatedReports page = (PageCreatedReports) getPage(); page.clearSearchPerformed(target); } }; searchForm.add(basicSearch); DropDownChoice reportTypeSelect = new DropDownChoice( ID_REPORT_TYPE_SELECT, new PropertyModel(model, ReportOutputSearchDto.F_REPORT_TYPE), new PropertyModel(model, ReportOutputSearchDto.F_REPORT_TYPES), new ChoiceRenderer()) { @Override protected String getNullValidDisplayValue() { return getString("pageCreatedReports.filter.reportType"); } }; reportTypeSelect.add( new OnChangeAjaxBehavior() { @Override protected void onUpdate(AjaxRequestTarget target) { PageCreatedReports page = (PageCreatedReports) getPage(); page.searchPerformed(target); } }); reportTypeSelect.setOutputMarkupId(true); reportTypeSelect.setNullValid(true); searchForm.add(reportTypeSelect); } } }
/** * Helper class that allows putting (almost) arbitrary objects into Activiti processes. * * <p>Generally, prism objects and containers and jaxb objects are stored in their XML form, * allowing for safe deserialization in potentially newer version of midpoint. * * <p>Other serializable items are stored as such. * * <p>There's a child class (JaxbValueContainer) that allows directly retrieving XML representation * of the object (if there's one). * * @author mederly */ public class SingleItemSerializationSafeContainerImpl<T> implements SerializationSafeContainer<T> { private static final long serialVersionUID = 7269803380754945968L; private static final Trace LOGGER = TraceManager.getTrace(SingleItemSerializationSafeContainerImpl.class); public static final int MAX_WIDTH = 500; // this is the actual (directly usable) value of the item private transient T actualValue; // if there's no need to encode the value, it is stored in the first attribute // if there is (e.g. for PrismObjects) the encoded value is stored in the second attribute private T valueForStorageWhenNotEncoded; protected String valueForStorageWhenEncoded; // beware, for JAXB, PRISM_OBJECT and PRISM_CONTAINER encoding schemes the value must be XML, as // it might be // exposed through JaxbValueContainer protected EncodingScheme encodingScheme; private transient PrismContext prismContext; public SingleItemSerializationSafeContainerImpl(T value, PrismContext prismContext) { Validate.notNull(prismContext, "prismContext must not be null"); this.prismContext = prismContext; setValue(value); } @Override public void setValue(T value) { this.actualValue = value; checkPrismContext(); if (value != null && prismContext.canSerialize(value)) { try { this.valueForStorageWhenEncoded = prismContext.xmlSerializer().serializeAnyData(value, new QName("value")); } catch (SchemaException e) { throw new SystemException( "Couldn't serialize value of type " + value.getClass() + ": " + e.getMessage(), e); } this.valueForStorageWhenNotEncoded = null; encodingScheme = EncodingScheme.PRISM; } else if (value == null || value instanceof Serializable) { this.valueForStorageWhenNotEncoded = value; this.valueForStorageWhenEncoded = null; encodingScheme = EncodingScheme.NONE; if (value instanceof Itemable) { throw new IllegalStateException( "Itemable value is used as not-encoded serializable item; value = " + value); } } else { throw new IllegalStateException( "Attempt to put non-serializable item " + value.getClass() + " into " + this.getClass().getSimpleName()); } } private void checkPrismContext() { Validate.notNull(prismContext, "In SerializationSafeContainer the prismContext is not set up"); } @Override public T getValue() { if (actualValue != null) { return actualValue; } if (valueForStorageWhenNotEncoded != null) { actualValue = valueForStorageWhenNotEncoded; return actualValue; } if (valueForStorageWhenEncoded != null) { if (prismContext == null) { throw new IllegalStateException( "PrismContext not set for SerializationSafeContainer holding " + StringUtils.abbreviate(valueForStorageWhenEncoded, MAX_WIDTH)); } if (encodingScheme == EncodingScheme.PRISM) { try { PrismValue prismValue = prismContext.parserFor(valueForStorageWhenEncoded).xml().parseItemValue(); actualValue = prismValue != null ? prismValue.getRealValue() : null; } catch (SchemaException e) { throw new SystemException( "Couldn't deserialize value from JAXB: " + StringUtils.abbreviate(valueForStorageWhenEncoded, MAX_WIDTH), e); } return actualValue; } else { throw new IllegalStateException("Unexpected encoding scheme " + encodingScheme); } } return null; } @Override public PrismContext getPrismContext() { return prismContext; } @Override public void setPrismContext(PrismContext prismContext) { this.prismContext = prismContext; } // for testing purposes @Override public void clearActualValue() { actualValue = null; } public enum EncodingScheme { PRISM, NONE }; @Override public String toString() { return "SerializationSafeContainer{" + "actualValue " + (actualValue != null ? "SET" : "NOT SET") + ", valueForStorageWhenNotEncoded=" + valueForStorageWhenNotEncoded + ", valueForStorageWhenEncoded='" + valueForStorageWhenEncoded + '\'' + ", encodingScheme=" + encodingScheme + ", prismContext " + (prismContext != null ? "SET" : "NOT SET") + '}'; } @Override public String debugDump(int indent) { StringBuilder sb = new StringBuilder(); if (actualValue != null) { debugDumpValue(indent, sb, actualValue); } else if (valueForStorageWhenNotEncoded != null) { debugDumpValue(indent, sb, valueForStorageWhenNotEncoded); } else if (valueForStorageWhenEncoded != null) { DebugUtil.debugDumpWithLabel(sb, "encoded value", valueForStorageWhenEncoded, indent); } else { DebugUtil.debugDumpWithLabel(sb, "value", "null", indent); } return sb.toString(); } private void debugDumpValue(int indent, StringBuilder sb, T value) { if (value instanceof DebugDumpable) { DebugUtil.debugDumpWithLabel(sb, "value", (DebugDumpable) value, indent); return; } String stringValue = null; if (value instanceof ExpressionType) { // brutal hack... String xml = null; try { xml = prismContext .xmlSerializer() .serializeRealValue(value, SchemaConstantsGenerated.C_EXPRESSION); stringValue = DebugUtil.fixIndentInMultiline(indent, DebugDumpable.INDENT_STRING, xml); } catch (SchemaException e) { LOGGER.warn("Couldn't serialize an expression: {}", value, e); } } if (stringValue == null) { stringValue = String.valueOf(value); } DebugUtil.debugDumpWithLabel(sb, "value", stringValue, indent); } }
/** @author mederly */ @Component public class GeneralChangeProcessor extends BaseChangeProcessor { private static final Trace LOGGER = TraceManager.getTrace(GeneralChangeProcessor.class); @Autowired private PrismContext prismContext; @Autowired private WfTaskUtil wfTaskUtil; @Autowired private JobController jobController; @Autowired private ActivitiEngine activitiEngine; @Autowired private BaseModelInvocationProcessingHelper baseModelInvocationProcessingHelper; @Autowired private BaseExternalizationHelper baseExternalizationHelper; @Autowired private BaseAuditHelper baseAuditHelper; @Autowired private GcpConfigurationHelper gcpConfigurationHelper; @Autowired private GcpExpressionHelper gcpExpressionHelper; @Autowired private GcpExternalizationHelper gcpExternalizationHelper; private GeneralChangeProcessorConfigurationType processorConfigurationType; // region Initialization and Configuration @PostConstruct public void init() { processorConfigurationType = gcpConfigurationHelper.configure(this); if (isEnabled()) { // print startup message int scenarios = processorConfigurationType.getScenario().size(); if (scenarios > 0) { LOGGER.info( getBeanName() + " initialized correctly (number of scenarios: " + scenarios + ")"); } else { LOGGER.warn( getBeanName() + " initialized correctly, but there are no scenarios - so it will never be invoked"); } } } private GeneralChangeProcessorScenarioType findScenario(String scenarioName) { for (GeneralChangeProcessorScenarioType scenario : processorConfigurationType.getScenario()) { if (scenarioName.equals(scenario.getName())) { return scenario; } } throw new SystemException("Scenario named " + scenarioName + " couldn't be found"); } private GcpScenarioBean getScenarioBean(Map<String, Object> variables) { String beanName = (String) variables.get(GcpProcessVariableNames.VARIABLE_MIDPOINT_SCENARIO_BEAN_NAME); return findScenarioBean(beanName); } public GcpScenarioBean findScenarioBean(String name) { if (name == null) { name = lowerFirstChar(DefaultGcpScenarioBean.class.getSimpleName()); } if (getBeanFactory().containsBean(name)) { return getBeanFactory().getBean(name, GcpScenarioBean.class); } else { throw new IllegalStateException("Scenario bean " + name + " couldn't be found."); } } private String lowerFirstChar(String name) { return Character.toLowerCase(name.charAt(0)) + name.substring(1); } public void disableScenario(String scenarioName) { findScenario(scenarioName).setEnabled(false); } public void enableScenario(String scenarioName) { findScenario(scenarioName).setEnabled(true); } // endregion // region Processing model invocation @Override public HookOperationMode processModelInvocation( ModelContext context, Task taskFromModel, OperationResult result) throws SchemaException { if (processorConfigurationType.getScenario().isEmpty()) { LOGGER.warn("No scenarios for " + getBeanName()); } for (GeneralChangeProcessorScenarioType scenarioType : processorConfigurationType.getScenario()) { GcpScenarioBean scenarioBean = findScenarioBean(scenarioType.getBeanName()); if (Boolean.FALSE.equals(scenarioType.isEnabled())) { LOGGER.trace("scenario {} is disabled, skipping", scenarioType.getName()); } else if (!gcpExpressionHelper.evaluateActivationCondition( scenarioType, context, taskFromModel, result)) { LOGGER.trace( "activationCondition was evaluated to FALSE for scenario named {}", scenarioType.getName()); } else if (!scenarioBean.determineActivation(scenarioType, context, taskFromModel, result)) { LOGGER.trace("scenarioBean decided to skip scenario named {}", scenarioType.getName()); } else { LOGGER.trace( "Applying scenario {} (process name {})", scenarioType.getName(), scenarioType.getProcessName()); return applyScenario(scenarioType, scenarioBean, context, taskFromModel, result); } } LOGGER.trace("No scenario found to be applicable, exiting the change processor."); return HookOperationMode.FOREGROUND; } private HookOperationMode applyScenario( GeneralChangeProcessorScenarioType scenarioType, GcpScenarioBean scenarioBean, ModelContext context, Task taskFromModel, OperationResult result) { try { // ========== preparing root task =========== JobCreationInstruction rootInstruction = baseModelInvocationProcessingHelper.createInstructionForRoot( this, context, taskFromModel); Job rootJob = baseModelInvocationProcessingHelper.createRootJob(rootInstruction, taskFromModel, result); // ========== preparing child task, starting WF process =========== JobCreationInstruction instruction = scenarioBean.prepareJobCreationInstruction( scenarioType, (LensContext<?>) context, rootJob, taskFromModel, result); jobController.createJob(instruction, rootJob, result); // ========== complete the action =========== baseModelInvocationProcessingHelper.logJobsBeforeStart(rootJob, result); rootJob.startWaitingForSubtasks(result); return HookOperationMode.BACKGROUND; } catch (SchemaException | ObjectNotFoundException | CommunicationException | ConfigurationException | RuntimeException e) { LoggingUtils.logException(LOGGER, "Workflow process(es) could not be started", e); result.recordFatalError("Workflow process(es) could not be started: " + e, e); return HookOperationMode.ERROR; // todo rollback - at least close open tasks, maybe stop workflow process instances } } // endregion // region Finalizing the processing @Override public void onProcessEnd(ProcessEvent event, Job job, OperationResult result) throws SchemaException, ObjectAlreadyExistsException, ObjectNotFoundException { Task task = job.getTask(); // we simply put model context back into parent task // (or if it is null, we set the task to skip model context processing) // it is safe to directly access the parent, because (1) it is in waiting state, (2) we are its // only child Task rootTask = task.getParentTask(result); SerializationSafeContainer<LensContextType> contextContainer = (SerializationSafeContainer<LensContextType>) event.getVariable(GcpProcessVariableNames.VARIABLE_MODEL_CONTEXT); LensContextType lensContextType = null; if (contextContainer != null) { contextContainer.setPrismContext(prismContext); lensContextType = contextContainer.getValue(); } if (lensContextType == null) { LOGGER.debug( GcpProcessVariableNames.VARIABLE_MODEL_CONTEXT + " not present in process, this means we should stop processing. Task = {}", rootTask); wfTaskUtil.setSkipModelContextProcessingProperty(rootTask, true, result); } else { LOGGER.debug( "Putting (changed or unchanged) value of {} into the task {}", GcpProcessVariableNames.VARIABLE_MODEL_CONTEXT, rootTask); wfTaskUtil.storeModelContext( rootTask, lensContextType.asPrismContainerValue().getContainer()); } rootTask.savePendingModifications(result); LOGGER.trace("onProcessEnd ending for task {}", task); } // endregion // region Externalization methods (including auditing) @Override public PrismObject<? extends WorkItemContents> externalizeWorkItemContents( org.activiti.engine.task.Task task, Map<String, Object> processInstanceVariables, OperationResult result) throws JAXBException, ObjectNotFoundException, SchemaException { return getScenarioBean(processInstanceVariables) .externalizeWorkItemContents(task, processInstanceVariables, result); } @Override public PrismObject<? extends ProcessInstanceState> externalizeProcessInstanceState( Map<String, Object> variables) throws JAXBException, SchemaException { PrismObject<ProcessInstanceState> state = baseExternalizationHelper.externalizeState(variables); ProcessSpecificState processSpecificState = getScenarioBean(variables).externalizeInstanceState(variables); state.asObjectable().setProcessSpecificState(processSpecificState); return state; } @Override public AuditEventRecord prepareProcessInstanceAuditRecord( Map<String, Object> variables, Job job, AuditEventStage stage, OperationResult result) { return getScenarioBean(variables) .prepareProcessInstanceAuditRecord(variables, job, stage, result); } @Override public AuditEventRecord prepareWorkItemAuditRecord( TaskEvent taskEvent, AuditEventStage stage, OperationResult result) throws WorkflowException { return getScenarioBean(taskEvent.getVariables()) .prepareWorkItemAuditRecord(taskEvent, stage, result); } // endregion }
/** * Interprets midPoint queries by translating them to hibernate (HQL) ones. * * <p>There are two parts: - filter translation, - paging translation. * * <p>As for filter translation, we traverse the filter depth-first, creating an isomorphic * structure of Restrictions. While creating them, we continually build a set of entity references * that are necessary to evaluate the query; these references are in the form of cartesian join of * entities from which each one can have a set of entities connected to it via left outer join. An * example: * * <p>from RUser u left join u.assignments a with ... left join u.organization o, RRole r left join * r.assignments a2 with ... * * <p>This structure is maintained in InterpretationContext, namely in the HibernateQuery being * prepared. (In order to produce HQL, we use ad-hoc "hibernate query model" in hqm package, rooted * in HibernateQuery class.) * * <p>Paging translation is done after filters are translated. It may add some entity references as * well, if they are not already present. * * @author lazyman * @author mederly */ public class QueryInterpreter2 { private static final Trace LOGGER = TraceManager.getTrace(QueryInterpreter2.class); private static final Map<Class, Matcher> AVAILABLE_MATCHERS; static { Map<Class, Matcher> matchers = new HashMap<>(); // default matcher with null key matchers.put(null, new DefaultMatcher()); matchers.put(PolyString.class, new PolyStringMatcher()); matchers.put(String.class, new StringMatcher()); AVAILABLE_MATCHERS = Collections.unmodifiableMap(matchers); } private SqlRepositoryConfiguration repoConfiguration; public QueryInterpreter2(SqlRepositoryConfiguration repoConfiguration) { this.repoConfiguration = repoConfiguration; } public SqlRepositoryConfiguration getRepoConfiguration() { return repoConfiguration; } public RootHibernateQuery interpret( ObjectQuery query, Class<? extends Containerable> type, Collection<SelectorOptions<GetOperationOptions>> options, PrismContext prismContext, boolean countingObjects, Session session) throws QueryException { Validate.notNull(type, "Type must not be null."); Validate.notNull(session, "Session must not be null."); Validate.notNull(prismContext, "Prism context must not be null."); if (LOGGER.isTraceEnabled()) { LOGGER.trace("Interpreting query for type '{}', query:\n{}", new Object[] {type, query}); } InterpretationContext context = new InterpretationContext(this, type, prismContext, session); interpretQueryFilter(context, query); interpretPagingAndSorting(context, query, countingObjects); RootHibernateQuery hibernateQuery = context.getHibernateQuery(); if (countingObjects) { hibernateQuery.addProjectionElement(new ProjectionElement("count(*)")); } else { String rootAlias = hibernateQuery.getPrimaryEntityAlias(); hibernateQuery.addProjectionElement(new ProjectionElement(rootAlias + ".fullObject")); // TODO other objects if parent is requested? if (context.isObject()) { hibernateQuery.addProjectionElement(new ProjectionElement(rootAlias + ".stringsCount")); hibernateQuery.addProjectionElement(new ProjectionElement(rootAlias + ".longsCount")); hibernateQuery.addProjectionElement(new ProjectionElement(rootAlias + ".datesCount")); hibernateQuery.addProjectionElement(new ProjectionElement(rootAlias + ".referencesCount")); hibernateQuery.addProjectionElement(new ProjectionElement(rootAlias + ".polysCount")); hibernateQuery.addProjectionElement(new ProjectionElement(rootAlias + ".booleansCount")); hibernateQuery.setResultTransformer(GetObjectResult.RESULT_TRANSFORMER); } else { hibernateQuery.addProjectionElement(new ProjectionElement(rootAlias + ".ownerOid")); hibernateQuery.setResultTransformer(GetContainerableResult.RESULT_TRANSFORMER); } } return hibernateQuery; } private void interpretQueryFilter(InterpretationContext context, ObjectQuery query) throws QueryException { if (query != null && query.getFilter() != null) { Condition c = interpretFilter(context, query.getFilter(), null); context.getHibernateQuery().addCondition(c); } } public Condition interpretFilter( InterpretationContext context, ObjectFilter filter, Restriction parent) throws QueryException { Restriction restriction = findAndCreateRestriction(filter, context, parent); Condition condition = restriction.interpret(); return condition; } private <T extends ObjectFilter> Restriction findAndCreateRestriction( T filter, InterpretationContext context, Restriction parent) throws QueryException { Validate.notNull(filter, "filter"); Validate.notNull(context, "context"); LOGGER.trace("Determining restriction for filter {}", filter); ItemPathResolver helper = context.getItemPathResolver(); JpaEntityDefinition baseEntityDefinition; if (parent != null) { baseEntityDefinition = parent.getBaseHqlEntityForChildren().getJpaDefinition(); } else { baseEntityDefinition = context.getRootEntityDefinition(); } Restriction restriction = findAndCreateRestrictionInternal(filter, context, parent, helper, baseEntityDefinition); LOGGER.trace("Restriction for {} is {}", filter.getClass().getSimpleName(), restriction); return restriction; } private <T extends ObjectFilter> Restriction findAndCreateRestrictionInternal( T filter, InterpretationContext context, Restriction parent, ItemPathResolver resolver, JpaEntityDefinition baseEntityDefinition) throws QueryException { // the order of processing restrictions can be important, so we do the selection via handwritten // code if (filter instanceof AndFilter) { return new AndRestriction(context, (AndFilter) filter, baseEntityDefinition, parent); } else if (filter instanceof OrFilter) { return new OrRestriction(context, (OrFilter) filter, baseEntityDefinition, parent); } else if (filter instanceof NotFilter) { return new NotRestriction(context, (NotFilter) filter, baseEntityDefinition, parent); } else if (filter instanceof InOidFilter) { return new InOidRestriction(context, (InOidFilter) filter, baseEntityDefinition, parent); } else if (filter instanceof OrgFilter) { return new OrgRestriction(context, (OrgFilter) filter, baseEntityDefinition, parent); } else if (filter instanceof TypeFilter) { TypeFilter typeFilter = (TypeFilter) filter; JpaEntityDefinition refinedEntityDefinition = resolver.findRestrictedEntityDefinition(baseEntityDefinition, typeFilter.getType()); return new TypeRestriction(context, typeFilter, refinedEntityDefinition, parent); } else if (filter instanceof ExistsFilter) { ExistsFilter existsFilter = (ExistsFilter) filter; ItemPath path = existsFilter.getFullPath(); ItemDefinition definition = existsFilter.getDefinition(); ProperDataSearchResult<JpaEntityDefinition> searchResult = resolver.findProperDataDefinition( baseEntityDefinition, path, definition, JpaEntityDefinition.class); if (searchResult == null) { throw new QueryException( "Path for ExistsFilter (" + path + ") doesn't point to a hibernate entity within " + baseEntityDefinition); } return new ExistsRestriction( context, existsFilter, searchResult.getEntityDefinition(), parent); } else if (filter instanceof RefFilter) { RefFilter refFilter = (RefFilter) filter; ItemPath path = refFilter.getFullPath(); ItemDefinition definition = refFilter.getDefinition(); ProperDataSearchResult<JpaReferenceDefinition> searchResult = resolver.findProperDataDefinition( baseEntityDefinition, path, definition, JpaReferenceDefinition.class); if (searchResult == null) { throw new QueryException( "Path for RefFilter (" + path + ") doesn't point to a reference item within " + baseEntityDefinition); } return new ReferenceRestriction( context, refFilter, searchResult.getEntityDefinition(), parent, searchResult.getLinkDefinition()); } else if (filter instanceof PropertyValueFilter) { PropertyValueFilter valFilter = (PropertyValueFilter) filter; ItemPath path = valFilter.getFullPath(); ItemDefinition definition = valFilter.getDefinition(); ProperDataSearchResult<JpaPropertyDefinition> propDefRes = resolver.findProperDataDefinition( baseEntityDefinition, path, definition, JpaPropertyDefinition.class); if (propDefRes == null) { throw new QueryException( "Couldn't find a proper restriction for a ValueFilter: " + valFilter.debugDump()); } // TODO can't be unified? if (propDefRes.getTargetDefinition() instanceof JpaAnyPropertyDefinition) { return new AnyPropertyRestriction( context, valFilter, propDefRes.getEntityDefinition(), parent, propDefRes.getLinkDefinition()); } else { return new PropertyRestriction( context, valFilter, propDefRes.getEntityDefinition(), parent, propDefRes.getLinkDefinition()); } } else if (filter instanceof NoneFilter || filter instanceof AllFilter || filter instanceof UndefinedFilter) { // these should be filtered out by the client throw new IllegalStateException( "Trivial filters are not supported by QueryInterpreter: " + filter.debugDump()); } else { throw new IllegalStateException("Unknown filter: " + filter.debugDump()); } } private void interpretPagingAndSorting( InterpretationContext context, ObjectQuery query, boolean countingObjects) throws QueryException { RootHibernateQuery hibernateQuery = context.getHibernateQuery(); String rootAlias = hibernateQuery.getPrimaryEntityAlias(); if (query != null && query.getPaging() instanceof ObjectPagingAfterOid) { ObjectPagingAfterOid paging = (ObjectPagingAfterOid) query.getPaging(); if (paging.getOidGreaterThan() != null) { Condition c = hibernateQuery.createSimpleComparisonCondition( rootAlias + ".oid", paging.getOidGreaterThan(), ">"); hibernateQuery.addCondition(c); } } if (!countingObjects && query != null && query.getPaging() != null) { if (query.getPaging() instanceof ObjectPagingAfterOid) { updatePagingAndSortingByOid( hibernateQuery, (ObjectPagingAfterOid) query.getPaging()); // very special case - ascending ordering by OID (nothing more) } else { updatePagingAndSorting(context, query.getPaging()); } } } protected void updatePagingAndSortingByOid( RootHibernateQuery hibernateQuery, ObjectPagingAfterOid paging) { String rootAlias = hibernateQuery.getPrimaryEntityAlias(); if (paging.getOrderBy() != null || paging.getDirection() != null || paging.getOffset() != null) { throw new IllegalArgumentException( "orderBy, direction nor offset is allowed on ObjectPagingAfterOid"); } hibernateQuery.addOrdering(rootAlias + ".oid", OrderDirection.ASCENDING); if (paging.getMaxSize() != null) { hibernateQuery.setMaxResults(paging.getMaxSize()); } } public <T extends Containerable> void updatePagingAndSorting( InterpretationContext context, ObjectPaging paging) throws QueryException { if (paging == null) { return; } RootHibernateQuery hibernateQuery = context.getHibernateQuery(); if (paging.getOffset() != null) { hibernateQuery.setFirstResult(paging.getOffset()); } if (paging.getMaxSize() != null) { hibernateQuery.setMaxResults(paging.getMaxSize()); } if (!paging.hasOrdering()) { return; } for (ObjectOrdering ordering : paging.getOrderingInstructions()) { addOrdering(context, ordering); } } private void addOrdering(InterpretationContext context, ObjectOrdering ordering) throws QueryException { ItemPath orderByPath = ordering.getOrderBy(); // TODO if we'd like to have order-by extension properties, we'd need to provide itemDefinition // for them ProperDataSearchResult<JpaDataNodeDefinition> result = context .getItemPathResolver() .findProperDataDefinition( context.getRootEntityDefinition(), orderByPath, null, JpaDataNodeDefinition.class); if (result == null) { LOGGER.error( "Unknown path '" + orderByPath + "', couldn't find definition for it, " + "list will not be ordered by it."); return; } JpaDataNodeDefinition targetDefinition = result.getLinkDefinition().getTargetDefinition(); if (targetDefinition instanceof JpaAnyContainerDefinition) { throw new QueryException( "Sorting based on extension item or attribute is not supported yet: " + orderByPath); } else if (targetDefinition instanceof JpaReferenceDefinition) { throw new QueryException("Sorting based on reference is not supported: " + orderByPath); } else if (result.getLinkDefinition().isMultivalued()) { throw new QueryException( "Sorting based on multi-valued item is not supported: " + orderByPath); } else if (targetDefinition instanceof JpaEntityDefinition) { throw new QueryException("Sorting based on entity is not supported: " + orderByPath); } else if (!(targetDefinition instanceof JpaPropertyDefinition)) { throw new IllegalStateException("Unknown item definition type: " + result.getClass()); } JpaEntityDefinition baseEntityDefinition = result.getEntityDefinition(); JpaPropertyDefinition orderByDefinition = (JpaPropertyDefinition) targetDefinition; String hqlPropertyPath = context .getItemPathResolver() .resolveItemPath( orderByPath, null, context.getPrimaryEntityAlias(), baseEntityDefinition, true) .getHqlPath(); if (RPolyString.class.equals(orderByDefinition.getJpaClass())) { hqlPropertyPath += ".orig"; } RootHibernateQuery hibernateQuery = context.getHibernateQuery(); if (ordering.getDirection() != null) { switch (ordering.getDirection()) { case ASCENDING: hibernateQuery.addOrdering(hqlPropertyPath, OrderDirection.ASCENDING); break; case DESCENDING: hibernateQuery.addOrdering(hqlPropertyPath, OrderDirection.DESCENDING); break; } } else { hibernateQuery.addOrdering(hqlPropertyPath, OrderDirection.ASCENDING); } } public <T extends Object> Matcher<T> findMatcher(T value) { return findMatcher(value != null ? (Class<T>) value.getClass() : null); } public <T extends Object> Matcher<T> findMatcher(Class<T> type) { Matcher<T> matcher = AVAILABLE_MATCHERS.get(type); if (matcher == null) { // we return default matcher matcher = AVAILABLE_MATCHERS.get(null); } return matcher; } }
/** @author shood */ public class ResourceDependencyEditor extends SimplePanel<List<ResourceObjectTypeDependencyType>> { private static enum ChangeState { SKIP, FIRST, LAST } private static final Trace LOGGER = TraceManager.getTrace(ResourceDependencyEditor.class); private static final String DOT_CLASS = ResourceDependencyEditor.class.getName() + "."; private static final String OPERATION_LOAD_RESOURCES = DOT_CLASS + "createResourceList"; private static final String ID_CONTAINER = "protectedContainer"; private static final String ID_REPEATER = "repeater"; private static final String ID_DEPENDENCY_LINK = "dependencyLink"; private static final String ID_DEPENDENCY_LINK_NAME = "dependencyLinkName"; private static final String ID_DEPENDENCY_BODY = "dependencyBodyContainer"; private static final String ID_ORDER = "order"; private static final String ID_STRICTNESS = "strictness"; private static final String ID_KIND = "kind"; private static final String ID_INTENT = "intent"; private static final String ID_REF = "resourceRef"; private static final String ID_ADD_BUTTON = "addButton"; private static final String ID_DELETE_BUTTON = "deleteDependency"; private static final String ID_T_ORDER = "orderTooltip"; private static final String ID_T_STRICTNESS = "strictnessTooltip"; private static final String ID_T_KIND = "kindTooltip"; private static final String ID_T_INTENT = "intentTooltip"; private static final String ID_T_RESOURCE_REF = "resourceRefTooltip"; private ChangeState changeState = ChangeState.FIRST; private Map<String, String> resourceMap = new HashMap<>(); public ResourceDependencyEditor(String id, IModel<List<ResourceObjectTypeDependencyType>> model) { super(id, model); } @Override public IModel<List<ResourceObjectTypeDependencyType>> getModel() { IModel<List<ResourceObjectTypeDependencyType>> model = super.getModel(); if (model.getObject() == null) { model.setObject(new ArrayList<ResourceObjectTypeDependencyType>()); } return model; } @Override protected void initLayout() { WebMarkupContainer container = new WebMarkupContainer(ID_CONTAINER); container.setOutputMarkupId(true); add(container); ListView repeater = new ListView<ResourceObjectTypeDependencyType>(ID_REPEATER, getModel()) { @Override protected void populateItem(final ListItem<ResourceObjectTypeDependencyType> item) { WebMarkupContainer linkContainer = new WebMarkupContainer(ID_DEPENDENCY_LINK); linkContainer.setOutputMarkupId(true); linkContainer.add(new AttributeModifier("href", createCollapseItemId(item, true))); item.add(linkContainer); Label linkLabel = new Label(ID_DEPENDENCY_LINK_NAME, createDependencyLabelModel(item)); linkContainer.add(linkLabel); AjaxLink delete = new AjaxLink(ID_DELETE_BUTTON) { @Override public void onClick(AjaxRequestTarget target) { deleteDependencyPerformed(target, item); } }; linkContainer.add(delete); WebMarkupContainer dependencyBody = new WebMarkupContainer(ID_DEPENDENCY_BODY); dependencyBody.setOutputMarkupId(true); dependencyBody.setMarkupId(createCollapseItemId(item, false).getObject()); if (changeState != ChangeState.SKIP) { dependencyBody.add( new AttributeModifier( "class", new AbstractReadOnlyModel<String>() { @Override public String getObject() { if (changeState == ChangeState.FIRST && item.getIndex() == 0) { return "panel-collapse collapse in"; } else if (changeState == ChangeState.LAST && item.getIndex() == (getModelObject().size() - 1)) { return "panel-collapse collapse in"; } else { return "panel-collapse collapse"; } } })); } item.add(dependencyBody); TextField order = new TextField<>( ID_ORDER, new PropertyModel<Integer>(item.getModelObject(), "order")); order.add(prepareAjaxOnComponentTagUpdateBehavior()); dependencyBody.add(order); DropDownChoice strictness = new DropDownChoice<>( ID_STRICTNESS, new PropertyModel<ResourceObjectTypeDependencyStrictnessType>( item.getModelObject(), "strictness"), WebMiscUtil.createReadonlyModelFromEnum( ResourceObjectTypeDependencyStrictnessType.class), new EnumChoiceRenderer<ResourceObjectTypeDependencyStrictnessType>(this)); strictness.add(prepareAjaxOnComponentTagUpdateBehavior()); dependencyBody.add(strictness); DropDownChoice kind = new DropDownChoice<>( ID_KIND, new PropertyModel<ShadowKindType>(item.getModelObject(), "kind"), WebMiscUtil.createReadonlyModelFromEnum(ShadowKindType.class), new EnumChoiceRenderer<ShadowKindType>(this)); kind.add(prepareAjaxOnComponentTagUpdateBehavior()); dependencyBody.add(kind); TextField intent = new TextField<>( ID_INTENT, new PropertyModel<String>(item.getModelObject(), "intent")); intent.add(prepareAjaxOnComponentTagUpdateBehavior()); dependencyBody.add(intent); DropDownChoice resource = new DropDownChoice<>( ID_REF, new PropertyModel<ObjectReferenceType>(item.getModelObject(), "resourceRef"), new AbstractReadOnlyModel<List<ObjectReferenceType>>() { @Override public List<ObjectReferenceType> getObject() { return createResourceList(); } }, new IChoiceRenderer<ObjectReferenceType>() { @Override public Object getDisplayValue(ObjectReferenceType object) { return createResourceReadLabel(object); } @Override public String getIdValue(ObjectReferenceType object, int index) { return Integer.toString(index); } }); resource.add(prepareAjaxOnComponentTagUpdateBehavior()); dependencyBody.add(resource); Label orderTooltip = new Label(ID_T_ORDER); orderTooltip.add(new InfoTooltipBehavior()); dependencyBody.add(orderTooltip); Label strictnessTooltip = new Label(ID_T_STRICTNESS); strictnessTooltip.add(new InfoTooltipBehavior()); dependencyBody.add(strictnessTooltip); Label kindTooltip = new Label(ID_T_KIND); kindTooltip.add(new InfoTooltipBehavior()); dependencyBody.add(kindTooltip); Label intentTooltip = new Label(ID_T_INTENT); intentTooltip.add(new InfoTooltipBehavior()); dependencyBody.add(intentTooltip); Label resourceRefTooltip = new Label(ID_T_RESOURCE_REF); resourceRefTooltip.add(new InfoTooltipBehavior()); dependencyBody.add(resourceRefTooltip); } }; repeater.setOutputMarkupId(true); container.add(repeater); AjaxLink add = new AjaxLink(ID_ADD_BUTTON) { @Override public void onClick(AjaxRequestTarget target) { addDependencyPerformed(target); } }; add(add); } private IModel<String> createDependencyLabelModel( final ListItem<ResourceObjectTypeDependencyType> item) { return new AbstractReadOnlyModel<String>() { @Override public String getObject() { StringBuilder sb = new StringBuilder(); ResourceObjectTypeDependencyType dep = item.getModelObject(); sb.append("#").append(item.getIndex() + 1).append(" - "); if (dep.getResourceRef() != null) { sb.append(resourceMap.get(dep.getResourceRef().getOid())).append(":"); } if (dep.getKind() != null) { sb.append(dep.getKind().toString()).append(":"); } if (dep.getIntent() != null) { sb.append(dep.getIntent()).append(":"); } sb.append(dep.getOrder()).append(":"); if (dep.getStrictness() != null) { sb.append(dep.getStrictness().toString()); } return sb.toString(); } }; } private AjaxFormComponentUpdatingBehavior prepareAjaxOnComponentTagUpdateBehavior() { return new AjaxFormComponentUpdatingBehavior("onBlur") { @Override protected void onUpdate(AjaxRequestTarget target) {} }; } private List<ObjectReferenceType> createResourceList() { resourceMap.clear(); OperationResult result = new OperationResult(OPERATION_LOAD_RESOURCES); Task task = getPageBase().createSimpleTask(OPERATION_LOAD_RESOURCES); List<PrismObject<ResourceType>> resources = null; List<ObjectReferenceType> references = new ArrayList<>(); try { resources = getPageBase() .getModelService() .searchObjects(ResourceType.class, new ObjectQuery(), null, task, result); result.recomputeStatus(); } catch (Exception e) { result.recordFatalError("Couldn't get resource list.", e); LoggingUtils.logException(LOGGER, "Couldn't get resource list.", e); } // TODO - show error somehow // if(!result.isSuccess()){ // getPageBase().showResult(result); // } if (resources != null) { ObjectReferenceType ref; for (PrismObject<ResourceType> r : resources) { resourceMap.put(r.getOid(), WebMiscUtil.getName(r)); ref = new ObjectReferenceType(); ref.setType(ResourceType.COMPLEX_TYPE); ref.setOid(r.getOid()); references.add(ref); } } return references; } private String createResourceReadLabel(ObjectReferenceType ref) { return resourceMap.get(ref.getOid()); } private WebMarkupContainer getMainContainer() { return (WebMarkupContainer) get(ID_CONTAINER); } private IModel<String> createCollapseItemId( final ListItem<ResourceObjectTypeDependencyType> item, final boolean appendSelector) { return new AbstractReadOnlyModel<String>() { @Override public String getObject() { StringBuilder sb = new StringBuilder(); if (appendSelector) { sb.append("#"); } sb.append("collapse").append(item.getId()); return sb.toString(); } }; } private void addDependencyPerformed(AjaxRequestTarget target) { ResourceObjectTypeDependencyType dependency = new ResourceObjectTypeDependencyType(); changeState = ChangeState.LAST; getModel().getObject().add(dependency); target.add(getMainContainer()); } private void deleteDependencyPerformed( AjaxRequestTarget target, ListItem<ResourceObjectTypeDependencyType> item) { changeState = ChangeState.SKIP; getModel().getObject().remove(item.getModelObject()); target.add(getMainContainer()); } }
/** * Read-through write-through per-session repository cache. * * <p>TODO doc TODO logging perf measurements * * @author Radovan Semancik */ public class RepositoryCache implements RepositoryService { private static ThreadLocal<Cache> cacheInstance = new ThreadLocal<>(); private RepositoryService repository; private static final Trace LOGGER = TraceManager.getTrace(RepositoryCache.class); private static final Trace PERFORMANCE_ADVISOR = TraceManager.getPerformanceAdvisorTrace(); private PrismContext prismContext; public RepositoryCache() {} public void setRepository(RepositoryService service, PrismContext prismContext) { Validate.notNull(service, "Repository service must not be null."); Validate.notNull(prismContext, "Prism context service must not be null."); this.repository = service; this.prismContext = prismContext; } private static Cache getCache() { return cacheInstance.get(); } public static void init() {} public static void destroy() { Cache.destroy(cacheInstance, LOGGER); } public static void enter() { Cache.enter(cacheInstance, Cache.class, LOGGER); } public static void exit() { Cache.exit(cacheInstance, LOGGER); } public static boolean exists() { return Cache.exists(cacheInstance); } public static String debugDump() { return Cache.debugDump(cacheInstance); } @Override public <T extends ObjectType> PrismObject<T> getObject( Class<T> type, String oid, Collection<SelectorOptions<GetOperationOptions>> options, OperationResult parentResult) throws ObjectNotFoundException, SchemaException { if (!isCacheable(type) || !nullOrHarmlessOptions(options)) { log("Cache: PASS {} ({})", oid, type.getSimpleName()); return repository.getObject(type, oid, options, parentResult); } Cache cache = getCache(); if (cache == null) { log("Cache: NULL {} ({})", oid, type.getSimpleName()); } else { PrismObject<T> object = (PrismObject) cache.getObject(oid); if (object != null) { // TODO: result? log("Cache: HIT {} ({})", oid, type.getSimpleName()); return object.clone(); } log("Cache: MISS {} ({})", oid, type.getSimpleName()); } PrismObject<T> object = repository.getObject(type, oid, null, parentResult); cacheObject(cache, object); return object; } private boolean isCacheable(Class<?> type) { if (type.equals(TaskType.class)) { return false; } // if (ShadowType.class.isAssignableFrom(type)) { // return false; // } return true; } @Override public <T extends ObjectType> String addObject( PrismObject<T> object, RepoAddOptions options, OperationResult parentResult) throws ObjectAlreadyExistsException, SchemaException { String oid = repository.addObject(object, options, parentResult); Cache cache = getCache(); // DON't cache the object here. The object may not have proper "JAXB" form, e.g. some pieces may // be // DOM element instead of JAXB elements. Not to cache it is safer and the performance loss // is acceptable. if (cache != null) { // Invalidate the cache entry if it happens to be there cache.removeObject(oid); cache.clearQueryResults(object.getCompileTimeClass()); } return oid; } @Override public <T extends ObjectType> SearchResultList<PrismObject<T>> searchObjects( Class<T> type, ObjectQuery query, Collection<SelectorOptions<GetOperationOptions>> options, OperationResult parentResult) throws SchemaException { if (!isCacheable(type) || !nullOrHarmlessOptions(options)) { log("Cache: PASS ({})", type.getSimpleName()); return repository.searchObjects(type, query, options, parentResult); } Cache cache = getCache(); if (cache == null) { log("Cache: NULL ({})", type.getSimpleName()); } else { SearchResultList queryResult = cache.getQueryResult(type, query, prismContext); if (queryResult != null) { log("Cache: HIT {} ({})", query, type.getSimpleName()); return queryResult.clone(); } log("Cache: MISS {} ({})", query, type.getSimpleName()); } // Cannot satisfy from cache, pass down to repository SearchResultList<PrismObject<T>> objects = repository.searchObjects(type, query, options, parentResult); if (cache != null && options == null) { for (PrismObject<T> object : objects) { cacheObject(cache, object); } cache.putQueryResult(type, query, objects, prismContext); } return objects; } /* (non-Javadoc) * @see com.evolveum.midpoint.repo.api.RepositoryService#searchObjectsIterative(java.lang.Class, com.evolveum.midpoint.prism.query.ObjectQuery, com.evolveum.midpoint.schema.ResultHandler, com.evolveum.midpoint.schema.result.OperationResult) */ @Override public <T extends ObjectType> SearchResultMetadata searchObjectsIterative( Class<T> type, ObjectQuery query, final ResultHandler<T> handler, Collection<SelectorOptions<GetOperationOptions>> options, OperationResult parentResult) throws SchemaException { // TODO use cached query result if applicable log("Cache: PASS searchObjectsIterative ({})", type.getSimpleName()); final Cache cache = getCache(); ResultHandler<T> myHandler = new ResultHandler<T>() { @Override public boolean handle(PrismObject<T> object, OperationResult parentResult) { cacheObject(cache, object); return handler.handle(object, parentResult); } }; return repository.searchObjectsIterative(type, query, myHandler, options, parentResult); } @Override public <T extends ObjectType> int countObjects( Class<T> type, ObjectQuery query, OperationResult parentResult) throws SchemaException { // TODO use cached query result if applicable log("Cache: PASS countObjects ({})", type.getSimpleName()); return repository.countObjects(type, query, parentResult); } @Override public <T extends ObjectType> void modifyObject( Class<T> type, String oid, Collection<? extends ItemDelta> modifications, OperationResult parentResult) throws ObjectNotFoundException, SchemaException, ObjectAlreadyExistsException { repository.modifyObject(type, oid, modifications, parentResult); // this changes the object. We are too lazy to apply changes ourselves, so just invalidate // the object in cache Cache cache = getCache(); if (cache != null) { cache.removeObject(oid); cache.clearQueryResults(type); } } @Override public <T extends ObjectType> void deleteObject( Class<T> type, String oid, OperationResult parentResult) throws ObjectNotFoundException { repository.deleteObject(type, oid, parentResult); Cache cache = getCache(); if (cache != null) { cache.removeObject(oid); cache.clearQueryResults(type); } } @Override public <F extends FocusType> PrismObject<F> searchShadowOwner( String shadowOid, Collection<SelectorOptions<GetOperationOptions>> options, OperationResult parentResult) throws ObjectNotFoundException { // TODO cache the search operation? PrismObject<F> ownerObject = repository.searchShadowOwner(shadowOid, options, parentResult); if (ownerObject != null && nullOrHarmlessOptions(options)) { cacheObject(getCache(), ownerObject); } return ownerObject; } private boolean nullOrHarmlessOptions(Collection<SelectorOptions<GetOperationOptions>> options) { if (options == null || options.isEmpty()) { return true; } if (options.size() > 1) { return false; } SelectorOptions<GetOperationOptions> selectorOptions = options.iterator().next(); if (!selectorOptions.isRoot()) { return false; } GetOperationOptions options1 = selectorOptions.getOptions(); if (options1 == null || options1.equals(new GetOperationOptions()) || options1.equals(GetOperationOptions.createAllowNotFound())) { return true; } return false; } @Override @Deprecated public PrismObject<UserType> listAccountShadowOwner( String accountOid, OperationResult parentResult) throws ObjectNotFoundException { return repository.listAccountShadowOwner(accountOid, parentResult); } @Override public <T extends ShadowType> List<PrismObject<T>> listResourceObjectShadows( String resourceOid, Class<T> resourceObjectShadowType, OperationResult parentResult) throws ObjectNotFoundException, SchemaException { return repository.listResourceObjectShadows( resourceOid, resourceObjectShadowType, parentResult); } /* (non-Javadoc) * @see com.evolveum.midpoint.repo.api.RepositoryService#getVersion(java.lang.Class, java.lang.String, com.evolveum.midpoint.schema.result.OperationResult) */ @Override public <T extends ObjectType> String getVersion( Class<T> type, String oid, OperationResult parentResult) throws ObjectNotFoundException, SchemaException { if (!isCacheable(type)) { log("Cache: PASS {} ({})", oid, type.getSimpleName()); return repository.getVersion(type, oid, parentResult); } Cache cache = getCache(); if (cache == null) { log("Cache: NULL {} ({})", oid, type.getSimpleName()); } else { String version = cache.getObjectVersion(oid); if (version != null) { log("Cache: HIT {} ({})", oid, type.getSimpleName()); return version; } log("Cache: MISS {} ({})", oid, type.getSimpleName()); } String version = repository.getVersion(type, oid, parentResult); cacheObjectVersion(cache, oid, version); return version; } /* (non-Javadoc) * @see com.evolveum.midpoint.repo.api.RepositoryService#getRepositoryDiag() */ @Override public RepositoryDiag getRepositoryDiag() { return repository.getRepositoryDiag(); } /* (non-Javadoc) * @see com.evolveum.midpoint.repo.api.RepositoryService#repositorySelfTest(com.evolveum.midpoint.schema.result.OperationResult) */ @Override public void repositorySelfTest(OperationResult parentResult) { repository.repositorySelfTest(parentResult); } @Override public void testOrgClosureConsistency(boolean repairIfNecessary, OperationResult testResult) { repository.testOrgClosureConsistency(repairIfNecessary, testResult); } private <T extends ObjectType> void cacheObject(Cache cache, PrismObject<T> object) { if (cache != null) { cache.putObject(object.getOid(), (PrismObject<ObjectType>) object.clone()); } } private <T extends ObjectType> void cacheObjectVersion(Cache cache, String oid, String version) { if (cache != null) { cache.putObjectVersion(oid, version); } } @Override public boolean isAnySubordinate(String upperOrgOid, Collection<String> lowerObjectOids) throws SchemaException { return repository.isAnySubordinate(upperOrgOid, lowerObjectOids); } private void log(String message, Object... params) { if (LOGGER.isTraceEnabled()) { LOGGER.trace(message, params); } if (PERFORMANCE_ADVISOR.isTraceEnabled()) { PERFORMANCE_ADVISOR.trace(message, params); } } }
/** * @author katkav * @author lazyman */ @PageDescriptor( url = "/admin/certification/definitions", action = { @AuthorizationAction( actionUri = PageAdminCertification.AUTH_CERTIFICATION_ALL, label = PageAdminCertification.AUTH_CERTIFICATION_ALL_LABEL, description = PageAdminCertification.AUTH_CERTIFICATION_ALL_DESCRIPTION), @AuthorizationAction( actionUri = PageAdminCertification.AUTH_CERTIFICATION_DEFINITIONS, label = PageAdminCertification.AUTH_CERTIFICATION_DEFINITIONS_LABEL, description = PageAdminCertification.AUTH_CERTIFICATION_DEFINITIONS_DESCRIPTION) }) public class PageCertDefinitions extends PageAdminWorkItems { private static final long serialVersionUID = 1L; private static final String ID_MAIN_FORM = "mainForm"; private static final String ID_TABLE = "table"; private static final String DOT_CLASS = PageCertDefinitions.class.getName() + "."; private static final String OPERATION_CREATE_CAMPAIGN = DOT_CLASS + "createCampaign"; private static final String OPERATION_DELETE_DEFINITION = DOT_CLASS + "deleteDefinition"; private static final Trace LOGGER = TraceManager.getTrace(PageCertDefinitions.class); private AccessCertificationDefinitionType singleDelete; public PageCertDefinitions() { initLayout(); } private void initLayout() { Form mainForm = new Form(ID_MAIN_FORM); add(mainForm); MainObjectListPanel<AccessCertificationDefinitionType> mainPanel = new MainObjectListPanel<AccessCertificationDefinitionType>( ID_TABLE, AccessCertificationDefinitionType.class, TableId.PAGE_CERT_DEFINITIONS_PANEL, null, this) { private static final long serialVersionUID = 1L; @Override protected IColumn<SelectableBean<AccessCertificationDefinitionType>, String> createCheckboxColumn() { return null; } @Override public void objectDetailsPerformed( AjaxRequestTarget target, AccessCertificationDefinitionType service) { PageCertDefinitions.this.detailsPerformed(target, service); } @Override protected List<IColumn<SelectableBean<AccessCertificationDefinitionType>, String>> createColumns() { return PageCertDefinitions.this.initColumns(); } @Override protected List<InlineMenuItem> createInlineMenu() { return null; } @Override protected void newObjectPerformed(AjaxRequestTarget target) { navigateToNext(PageCertDefinition.class); } }; mainPanel.setAdditionalBoxCssClasses(GuiStyleConstants.CLASS_OBJECT_CERT_DEF_BOX_CSS_CLASSES); mainForm.add(mainPanel); } private MainObjectListPanel<AccessCertificationDefinitionType> getDefinitionsTable() { return (MainObjectListPanel<AccessCertificationDefinitionType>) get(createComponentPath(ID_MAIN_FORM, ID_TABLE)); } private IModel<String> createDeleteConfirmString() { return new AbstractReadOnlyModel<String>() { @Override public String getObject() { if (singleDelete == null) { return ""; } else { return createStringResource( "PageCertDefinitions.deleteDefinitionConfirmSingle", singleDelete.getName()) .getString(); } } }; } private List<IColumn<SelectableBean<AccessCertificationDefinitionType>, String>> initColumns() { List<IColumn<SelectableBean<AccessCertificationDefinitionType>, String>> columns = new ArrayList<>(); IColumn column; column = new PropertyColumn( createStringResource("PageCertDefinitions.table.description"), "value.description"); columns.add(column); column = new MultiButtonColumn<SelectableBean<AccessCertificationDefinitionType>>(new Model(), 3) { private final String[] captionKeys = { "PageCertDefinitions.button.createCampaign", "PageCertDefinitions.button.showCampaigns", "PageCertDefinitions.button.deleteDefinition" }; private final DoubleButtonColumn.BUTTON_COLOR_CLASS[] colors = { DoubleButtonColumn.BUTTON_COLOR_CLASS.PRIMARY, DoubleButtonColumn.BUTTON_COLOR_CLASS.DEFAULT, DoubleButtonColumn.BUTTON_COLOR_CLASS.DANGER }; @Override public String getCaption(int id) { return PageCertDefinitions.this.createStringResource(captionKeys[id]).getString(); } @Override public String getButtonColorCssClass(int id) { return colors[id].toString(); } @Override public void clickPerformed( int id, AjaxRequestTarget target, IModel<SelectableBean<AccessCertificationDefinitionType>> model) { switch (id) { case 0: createCampaignPerformed(target, model.getObject().getValue()); break; case 1: showCampaignsPerformed(target, model.getObject().getValue()); break; case 2: deleteConfirmation(target, model.getObject().getValue()); break; } } }; columns.add(column); return columns; } protected void detailsPerformed( AjaxRequestTarget target, AccessCertificationDefinitionType service) { PageParameters parameters = new PageParameters(); parameters.add(OnePageParameterEncoder.PARAMETER, service.getOid()); navigateToNext(PageCertDefinition.class, parameters); } private void showCampaignsPerformed( AjaxRequestTarget target, AccessCertificationDefinitionType definition) { PageParameters parameters = new PageParameters(); parameters.add(OnePageParameterEncoder.PARAMETER, definition.getOid()); navigateToNext(PageCertCampaigns.class, parameters); } private void createCampaignPerformed( AjaxRequestTarget target, AccessCertificationDefinitionType definition) { LOGGER.debug("Create certification campaign performed for {}", definition.asPrismObject()); OperationResult result = new OperationResult(OPERATION_CREATE_CAMPAIGN); try { Task task = createSimpleTask(OPERATION_CREATE_CAMPAIGN); getCertificationService().createCampaign(definition.getOid(), task, result); } catch (Exception ex) { result.recordFatalError(ex); } finally { result.computeStatusIfUnknown(); } showResult(result); target.add(getFeedbackPanel()); } private void deleteConfirmation( AjaxRequestTarget target, AccessCertificationDefinitionType definition) { this.singleDelete = definition; showMainPopup(getDeleteDefinitionConfirmationPanel(), target); } private void deleteDefinitionPerformed( AjaxRequestTarget target, AccessCertificationDefinitionType definition) { OperationResult result = new OperationResult(OPERATION_DELETE_DEFINITION); try { Task task = createSimpleTask(OPERATION_DELETE_DEFINITION); ObjectDelta<AccessCertificationDefinitionType> delta = ObjectDelta.createDeleteDelta( AccessCertificationDefinitionType.class, definition.getOid(), getPrismContext()); getModelService() .executeChanges(WebComponentUtil.createDeltaCollection(delta), null, task, result); } catch (Exception ex) { result.recordPartialError("Couldn't delete campaign definition.", ex); LoggingUtils.logUnexpectedException(LOGGER, "Couldn't delete campaign definition", ex); } result.computeStatusIfUnknown(); if (result.isSuccess()) { result.recordStatus( OperationResultStatus.SUCCESS, "The definition has been successfully deleted."); } getDefinitionsTable().clearCache(); showResult(result); target.add(getFeedbackPanel(), getDefinitionsTable()); } private Popupable getDeleteDefinitionConfirmationPanel() { return new ConfirmationPanel(getMainPopupBodyId(), createDeleteConfirmString()) { @Override public void yesPerformed(AjaxRequestTarget target) { ModalWindow modalWindow = findParent(ModalWindow.class); if (modalWindow != null) { modalWindow.close(target); deleteDefinitionPerformed(target, singleDelete); } } }; } }
/** * Nested Operation Result. * * <p>This class provides information for better error handling in complex operations. It contains a * status (success, failure, warning, ...) and an error message. It also contains a set of * sub-results - results on inner operations. * * <p>This object can be used by GUI to display smart (and interactive) error information. It can * also be used by the client code to detect deeper problems in the invocations, retry or otherwise * compensate for the errors or decide how severe the error was and it is possible to proceed. * * @author lazyman * @author Radovan Semancik */ public class OperationResult implements Serializable, DebugDumpable, Cloneable { private static final long serialVersionUID = -2467406395542291044L; private static final String INDENT_STRING = " "; /** * This constant provides count threshold for same subresults (same operation and status) during * summarize operation. */ private static final int SUBRESULT_STRIP_THRESHOLD = 10; public static final String CONTEXT_IMPLEMENTATION_CLASS = "implementationClass"; public static final String CONTEXT_PROGRESS = "progress"; public static final String CONTEXT_OID = "oid"; public static final String CONTEXT_OBJECT = "object"; public static final String CONTEXT_ITEM = "item"; public static final String CONTEXT_TASK = "task"; public static final String CONTEXT_RESOURCE = "resource"; public static final String PARAM_OID = "oid"; public static final String PARAM_TYPE = "type"; public static final String PARAM_OPTIONS = "options"; public static final String PARAM_TASK = "task"; public static final String PARAM_OBJECT = "object"; public static final String PARAM_QUERY = "query"; public static final String RETURN_COUNT = "count"; public static final String RETURN_BACKGROUND_TASK_OID = "backgroundTaskOid"; private static long TOKEN_COUNT = 1000000000000000000L; private String operation; private OperationResultStatus status; private Map<String, Serializable> params; private Map<String, Serializable> context; private Map<String, Serializable> returns; private long token; private String messageCode; private String message; private String localizationMessage; private List<Serializable> localizationArguments; private Throwable cause; private int count = 1; private List<OperationResult> subresults; private List<String> details; private boolean summarizeErrors; private boolean summarizePartialErrors; private boolean summarizeSuccesses; private boolean minor = false; private static final Trace LOGGER = TraceManager.getTrace(OperationResult.class); public OperationResult(String operation) { this(operation, null, OperationResultStatus.UNKNOWN, 0, null, null, null, null, null); } public OperationResult(String operation, String messageCode, String message) { this(operation, null, OperationResultStatus.SUCCESS, 0, messageCode, message, null, null, null); } public OperationResult(String operation, long token, String messageCode, String message) { this( operation, null, OperationResultStatus.SUCCESS, token, messageCode, message, null, null, null); } public OperationResult(String operation, OperationResultStatus status, String message) { this(operation, null, status, 0, null, message, null, null, null); } public OperationResult( String operation, OperationResultStatus status, String messageCode, String message) { this(operation, null, status, 0, messageCode, message, null, null, null); } public OperationResult( String operation, OperationResultStatus status, long token, String messageCode, String message) { this(operation, null, status, token, messageCode, message, null, null, null); } public OperationResult( String operation, OperationResultStatus status, long token, String messageCode, String message, Throwable cause) { this(operation, null, status, token, messageCode, message, null, cause, null); } public OperationResult( String operation, Map<String, Serializable> params, OperationResultStatus status, long token, String messageCode, String message) { this(operation, params, status, token, messageCode, message, null, null, null); } public OperationResult( String operation, Map<String, Serializable> params, OperationResultStatus status, long token, String messageCode, String message, List<OperationResult> subresults) { this(operation, params, status, token, messageCode, message, null, null, subresults); } public OperationResult( String operation, Map<String, Serializable> params, OperationResultStatus status, long token, String messageCode, String message, String localizationMessage, Throwable cause, List<OperationResult> subresults) { this( operation, params, status, token, messageCode, message, localizationMessage, null, cause, subresults); } public OperationResult( String operation, Map<String, Serializable> params, OperationResultStatus status, long token, String messageCode, String message, String localizationMessage, List<Serializable> localizationArguments, Throwable cause, List<OperationResult> subresults) { this( operation, params, null, null, status, token, messageCode, message, localizationMessage, null, cause, subresults); } public OperationResult( String operation, Map<String, Serializable> params, Map<String, Serializable> context, Map<String, Serializable> returns, OperationResultStatus status, long token, String messageCode, String message, String localizationMessage, List<Serializable> localizationArguments, Throwable cause, List<OperationResult> subresults) { if (StringUtils.isEmpty(operation)) { throw new IllegalArgumentException("Operation argument must not be null or empty."); } if (status == null) { throw new IllegalArgumentException("Operation status must not be null."); } this.operation = operation; this.params = params; this.context = context; this.returns = returns; this.status = status; this.token = token; this.messageCode = messageCode; this.message = message; this.localizationMessage = localizationMessage; this.localizationArguments = localizationArguments; this.cause = cause; this.subresults = subresults; this.details = new ArrayList<String>(); } public OperationResult createSubresult(String operation) { OperationResult subresult = new OperationResult(operation); addSubresult(subresult); return subresult; } public OperationResult createMinorSubresult(String operation) { OperationResult subresult = createSubresult(operation); subresult.minor = true; return subresult; } /** * Contains operation name. Operation name must be defined as {@link String} constant in module * interface with description and possible parameters. It can be used for further processing. It * will be used as key for translation in admin-gui. * * @return always return non null, non empty string */ public String getOperation() { return operation; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } public void incrementCount() { this.count++; } public boolean isSummarizeErrors() { return summarizeErrors; } public void setSummarizeErrors(boolean summarizeErrors) { this.summarizeErrors = summarizeErrors; } public boolean isSummarizePartialErrors() { return summarizePartialErrors; } public void setSummarizePartialErrors(boolean summarizePartialErrors) { this.summarizePartialErrors = summarizePartialErrors; } public boolean isSummarizeSuccesses() { return summarizeSuccesses; } public void setSummarizeSuccesses(boolean summarizeSuccesses) { this.summarizeSuccesses = summarizeSuccesses; } public boolean isEmpty() { return (status == null || status == OperationResultStatus.UNKNOWN) && (subresults == null || subresults.isEmpty()); } /** * Method returns list of operation subresults @{link {@link OperationResult}. * * @return never returns null */ public List<OperationResult> getSubresults() { if (subresults == null) { subresults = new ArrayList<OperationResult>(); } return subresults; } /** @return last subresult, or null if there are no subresults. */ public OperationResult getLastSubresult() { if (subresults == null || subresults.isEmpty()) { return null; } else { return subresults.get(subresults.size() - 1); } } public void removeLastSubresult() { if (subresults != null && !subresults.isEmpty()) { subresults.remove(subresults.size() - 1); } } /** @return last subresult status, or null if there are no subresults. */ public OperationResultStatus getLastSubresultStatus() { OperationResult last = getLastSubresult(); return last != null ? last.getStatus() : null; } public void addSubresult(OperationResult subresult) { getSubresults().add(subresult); } public OperationResult findSubresult(String operation) { if (subresults == null) { return null; } for (OperationResult subResult : getSubresults()) { if (operation.equals(subResult.getOperation())) { return subResult; } } return null; } public List<OperationResult> findSubresults(String operation) { List<OperationResult> found = new ArrayList<>(); if (subresults == null) { return found; } for (OperationResult subResult : getSubresults()) { if (operation.equals(subResult.getOperation())) { found.add(subResult); } } return found; } /** * Contains operation status as defined in {@link OperationResultStatus} * * @return never returns null */ public OperationResultStatus getStatus() { return status; } public void setStatus(OperationResultStatus status) { this.status = status; } /** * Returns true if the result is success. * * <p>This returns true if the result is absolute success. Presence of partial failures or * warnings fail this test. * * @return true if the result is success. */ public boolean isSuccess() { return (status == OperationResultStatus.SUCCESS); } public boolean isWarning() { return status == OperationResultStatus.WARNING; } /** * Returns true if the result is acceptable for further processing. * * <p>In other words: if there were no fatal errors. Warnings and partial errors are acceptable. * Yet, this test also fails if the operation state is not known. * * @return true if the result is acceptable for further processing. */ public boolean isAcceptable() { return (status != OperationResultStatus.FATAL_ERROR); } public boolean isUnknown() { return (status == OperationResultStatus.UNKNOWN); } public boolean isInProgress() { return (status == OperationResultStatus.IN_PROGRESS); } public boolean isError() { return (status == OperationResultStatus.FATAL_ERROR) || (status == OperationResultStatus.PARTIAL_ERROR); } public boolean isFatalError() { return (status == OperationResultStatus.FATAL_ERROR); } public boolean isPartialError() { return (status == OperationResultStatus.PARTIAL_ERROR); } public boolean isHandledError() { return (status == OperationResultStatus.HANDLED_ERROR); } public boolean isNotApplicable() { return (status == OperationResultStatus.NOT_APPLICABLE); } /** Set all error status in this result and all subresults as handled. */ public void setErrorsHandled() { if (isError()) { setStatus(OperationResultStatus.HANDLED_ERROR); } for (OperationResult subresult : getSubresults()) { subresult.setErrorsHandled(); } } /** * Computes operation result status based on subtask status and sets an error message if the * status is FATAL_ERROR. * * @param errorMessage error message */ public void computeStatus(String errorMessage) { computeStatus(errorMessage, errorMessage); } public void computeStatus(String errorMessage, String warnMessage) { Validate.notEmpty(errorMessage, "Error message must not be null."); // computeStatus sets a message if none is set, // therefore we need to check before calling computeStatus boolean noMessage = StringUtils.isEmpty(message); computeStatus(); switch (status) { case FATAL_ERROR: case PARTIAL_ERROR: if (noMessage) { message = errorMessage; } break; case UNKNOWN: case WARNING: case NOT_APPLICABLE: if (noMessage) { if (StringUtils.isNotEmpty(warnMessage)) { message = warnMessage; } else { message = errorMessage; } } break; } } /** Computes operation result status based on subtask status. */ public void computeStatus() { if (getSubresults().isEmpty()) { if (status == OperationResultStatus.UNKNOWN) { status = OperationResultStatus.SUCCESS; } return; } if (status == OperationResultStatus.FATAL_ERROR) { return; } OperationResultStatus newStatus = OperationResultStatus.UNKNOWN; boolean allSuccess = true; boolean allNotApplicable = true; String newMessage = null; for (OperationResult sub : getSubresults()) { if (sub.getStatus() != OperationResultStatus.NOT_APPLICABLE) { allNotApplicable = false; } if (sub.getStatus() == OperationResultStatus.FATAL_ERROR) { status = OperationResultStatus.FATAL_ERROR; if (message == null) { message = sub.getMessage(); } else { message = message + ": " + sub.getMessage(); } return; } if (sub.getStatus() == OperationResultStatus.IN_PROGRESS) { status = OperationResultStatus.IN_PROGRESS; if (message == null) { message = sub.getMessage(); } else { message = message + ": " + sub.getMessage(); } return; } if (sub.getStatus() == OperationResultStatus.PARTIAL_ERROR) { newStatus = OperationResultStatus.PARTIAL_ERROR; newMessage = sub.getMessage(); } if (newStatus != OperationResultStatus.PARTIAL_ERROR) { if (sub.getStatus() == OperationResultStatus.HANDLED_ERROR) { newStatus = OperationResultStatus.HANDLED_ERROR; newMessage = sub.getMessage(); } } if (sub.getStatus() != OperationResultStatus.SUCCESS && sub.getStatus() != OperationResultStatus.NOT_APPLICABLE) { allSuccess = false; } if (newStatus != OperationResultStatus.HANDLED_ERROR) { if (sub.getStatus() == OperationResultStatus.WARNING) { newStatus = OperationResultStatus.WARNING; newMessage = sub.getMessage(); } } } if (allNotApplicable && !getSubresults().isEmpty()) { status = OperationResultStatus.NOT_APPLICABLE; } if (allSuccess && !getSubresults().isEmpty()) { status = OperationResultStatus.SUCCESS; } else { status = newStatus; if (message == null) { message = newMessage; } else { message = message + ": " + newMessage; } } } /** * Used when the result contains several composite sub-result that are of equivalent meaning. If * all of them fail the result will be fatal error as well. If only some of them fail the result * will be partial error. Handled error is considered a success. */ public void computeStatusComposite() { if (getSubresults().isEmpty()) { if (status == OperationResultStatus.UNKNOWN) { status = OperationResultStatus.NOT_APPLICABLE; } return; } boolean allFatalError = true; boolean allNotApplicable = true; boolean hasInProgress = false; boolean hasHandledError = false; boolean hasError = false; boolean hasWarning = false; for (OperationResult sub : getSubresults()) { if (sub.getStatus() != OperationResultStatus.NOT_APPLICABLE) { allNotApplicable = false; } if (sub.getStatus() != OperationResultStatus.FATAL_ERROR) { allFatalError = false; } if (sub.getStatus() == OperationResultStatus.FATAL_ERROR) { hasError = true; if (message == null) { message = sub.getMessage(); } else { message = message + ", " + sub.getMessage(); } } if (sub.getStatus() == OperationResultStatus.PARTIAL_ERROR) { hasError = true; if (message == null) { message = sub.getMessage(); } else { message = message + ", " + sub.getMessage(); } } if (sub.getStatus() == OperationResultStatus.HANDLED_ERROR) { hasHandledError = true; if (message == null) { message = sub.getMessage(); } else { message = message + ", " + sub.getMessage(); } } if (sub.getStatus() == OperationResultStatus.IN_PROGRESS) { hasInProgress = true; if (message == null) { message = sub.getMessage(); } else { message = message + ", " + sub.getMessage(); } } if (sub.getStatus() == OperationResultStatus.WARNING) { hasWarning = true; if (message == null) { message = sub.getMessage(); } else { message = message + ", " + sub.getMessage(); } } } if (allNotApplicable) { status = OperationResultStatus.NOT_APPLICABLE; } else if (allFatalError) { status = OperationResultStatus.FATAL_ERROR; } else if (hasInProgress) { status = OperationResultStatus.IN_PROGRESS; } else if (hasError) { status = OperationResultStatus.PARTIAL_ERROR; } else if (hasWarning) { status = OperationResultStatus.WARNING; } else if (hasHandledError) { status = OperationResultStatus.HANDLED_ERROR; } else { status = OperationResultStatus.SUCCESS; } } public OperationResultStatus getComputeStatus() { OperationResultStatus origStatus = status; String origMessage = message; computeStatus(); OperationResultStatus computedStatus = status; status = origStatus; message = origMessage; return computedStatus; } public void computeStatusIfUnknown() { if (isUnknown()) { computeStatus(); } } public void recomputeStatus() { // Only recompute if there are subresults, otherwise keep original // status if (subresults != null && !subresults.isEmpty()) { computeStatus(); } } public void recomputeStatus(String message) { // Only recompute if there are subresults, otherwise keep original // status if (subresults != null && !subresults.isEmpty()) { computeStatus(message); } } public void recomputeStatus(String errorMessage, String warningMessage) { // Only recompute if there are subresults, otherwise keep original // status if (subresults != null && !subresults.isEmpty()) { computeStatus(errorMessage, warningMessage); } } public void recordSuccessIfUnknown() { if (isUnknown()) { recordSuccess(); } } public void recordNotApplicableIfUnknown() { if (isUnknown()) { status = OperationResultStatus.NOT_APPLICABLE; } } /** * Method returns {@link Map} with operation parameters. Parameters keys are described in module * interface for every operation. * * @return never returns null */ public Map<String, Serializable> getParams() { if (params == null) { params = new HashMap<String, Serializable>(); } return params; } public void addParam(String paramName, Serializable paramValue) { getParams().put(paramName, paramValue); } public void addArbitraryObjectAsParam(String paramName, Object paramValue) { addParam(paramName, String.valueOf(paramValue)); } // Copies a collection to a OperationResult's param field. Primarily used to overcome the fact // that Collection is not Serializable public void addCollectionOfSerializablesAsParam( String paramName, Collection<? extends Serializable> paramValue) { addParam(paramName, paramValue != null ? new ArrayList(paramValue) : null); } public void addCollectionOfSerializablesAsReturn( String name, Collection<? extends Serializable> value) { addReturn(name, value != null ? new ArrayList(value) : null); } public void addArbitraryCollectionAsParam(String paramName, Collection values) { if (values != null) { ArrayList<String> valuesAsStrings = new ArrayList<String>(); for (Object value : values) { valuesAsStrings.add(String.valueOf(value)); } addParam(paramName, valuesAsStrings); } else { addParam(paramName, null); } } public void addParams(String[] names, Serializable... objects) { if (names.length != objects.length) { throw new IllegalArgumentException( "Bad result parameters size, names '" + names.length + "', objects '" + objects.length + "'."); } for (int i = 0; i < names.length; i++) { addParam(names[i], objects[i]); } } public Map<String, Serializable> getContext() { if (context == null) { context = new HashMap<String, Serializable>(); } return context; } @SuppressWarnings("unchecked") public <T> T getContext(Class<T> type, String contextName) { return (T) getContext().get(contextName); } public void addContext(String contextName, Serializable value) { getContext().put(contextName, value); } public Map<String, Serializable> getReturns() { if (returns == null) { returns = new HashMap<>(); } return returns; } public void addReturn(String returnName, Serializable value) { getReturns().put(returnName, value); } public Serializable getReturn(String returnName) { return getReturns().get(returnName); } /** @return Contains random long number, for better searching in logs. */ public long getToken() { if (token == 0) { token = TOKEN_COUNT++; } return token; } /** * Contains mesage code based on module error catalog. * * @return Can return null. */ public String getMessageCode() { return messageCode; } /** * @return Method returns operation result message. Message is required. It will be key for * translation in admin-gui. */ public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } /** @return Method returns message key for translation, can be null. */ public String getLocalizationMessage() { return localizationMessage; } /** @return Method returns arguments if needed for localization, can be null. */ public List<Serializable> getLocalizationArguments() { return localizationArguments; } /** @return Method returns operation result exception. Not required, can be null. */ public Throwable getCause() { return cause; } public void recordSuccess() { // Success, no message or other explanation is needed. status = OperationResultStatus.SUCCESS; } public void recordInProgress() { status = OperationResultStatus.IN_PROGRESS; } public void recordUnknown() { status = OperationResultStatus.UNKNOWN; } public void recordFatalError(Throwable cause) { recordStatus(OperationResultStatus.FATAL_ERROR, cause.getMessage(), cause); } /** * If the operation is an error then it will switch the status to EXPECTED_ERROR. This is used if * the error is expected and properly handled. */ public void muteError() { if (isError()) { status = OperationResultStatus.HANDLED_ERROR; } } public void muteLastSubresultError() { OperationResult lastSubresult = getLastSubresult(); if (lastSubresult != null) { lastSubresult.muteError(); } } public void recordPartialError(Throwable cause) { recordStatus(OperationResultStatus.PARTIAL_ERROR, cause.getMessage(), cause); } public void recordWarning(Throwable cause) { recordStatus(OperationResultStatus.WARNING, cause.getMessage(), cause); } public void recordStatus(OperationResultStatus status, Throwable cause) { this.status = status; this.cause = cause; // No other message was given, so use message from the exception // not really correct, but better than nothing. message = cause.getMessage(); } public void recordFatalError(String message, Throwable cause) { recordStatus(OperationResultStatus.FATAL_ERROR, message, cause); } public void recordPartialError(String message, Throwable cause) { recordStatus(OperationResultStatus.PARTIAL_ERROR, message, cause); } public void recordWarning(String message, Throwable cause) { recordStatus(OperationResultStatus.WARNING, message, cause); } public void recordHandledError(String message) { recordStatus(OperationResultStatus.HANDLED_ERROR, message); } public void recordHandledError(String message, Throwable cause) { recordStatus(OperationResultStatus.HANDLED_ERROR, message, cause); } public void recordHandledError(Throwable cause) { recordStatus(OperationResultStatus.HANDLED_ERROR, cause.getMessage(), cause); } public void recordStatus(OperationResultStatus status, String message, Throwable cause) { this.status = status; this.message = message; this.cause = cause; } public void recordFatalError(String message) { recordStatus(OperationResultStatus.FATAL_ERROR, message); } public void recordPartialError(String message) { recordStatus(OperationResultStatus.PARTIAL_ERROR, message); } public void recordWarning(String message) { recordStatus(OperationResultStatus.WARNING, message); } /** * Records result from a common exception type. This automatically determines status and also sets * appropriate message. * * @param exception common exception */ public void record(CommonException exception) { // TODO: switch to a localized message later // Exception is a fatal error in this context recordFatalError(exception.getOperationResultMessage(), exception); } public void recordStatus(OperationResultStatus status, String message) { this.status = status; this.message = message; } /** * Returns true if result status is UNKNOWN or any of the subresult status is unknown (recursive). * * <p>May come handy in tests to check if all the operations fill out the status as they should. */ public boolean hasUnknownStatus() { if (status == OperationResultStatus.UNKNOWN) { return true; } for (OperationResult subresult : getSubresults()) { if (subresult.hasUnknownStatus()) { return true; } } return false; } public void appendDetail(String detailLine) { // May be switched to a more structured method later details.add(detailLine); } public List<String> getDetail() { return details; } @Override public String toString() { return "R(" + operation + " " + status + " " + message + ")"; } public static OperationResult createOperationResult(OperationResultType result) { if (result == null) { return null; } Map<String, Serializable> params = ParamsTypeUtil.fromParamsType(result.getParams()); // if (result.getParams() != null) { // params = new HashMap<String, Serializable>(); // for (EntryType entry : result.getParams().getEntry()) { // params.put(entry.getKey(), (Serializable) entry.getEntryValue()); // } // } Map<String, Serializable> context = ParamsTypeUtil.fromParamsType(result.getContext()); // if (result.getContext() != null) { // context = new HashMap<String, Serializable>(); // for (EntryType entry : result.getContext().getEntry()) { // context.put(entry.getKey(), (Serializable) entry.getEntryValue()); // } // } Map<String, Serializable> returns = ParamsTypeUtil.fromParamsType(result.getReturns()); // if (result.getReturns() != null) { // returns = new HashMap<String, Serializable>(); // for (EntryType entry : result.getReturns().getEntry()) { // returns.put(entry.getKey(), (Serializable) entry.getEntryValue()); // } // } List<OperationResult> subresults = null; if (!result.getPartialResults().isEmpty()) { subresults = new ArrayList<OperationResult>(); for (OperationResultType subResult : result.getPartialResults()) { subresults.add(createOperationResult(subResult)); } } LocalizedMessageType message = result.getLocalizedMessage(); String localizedMessage = message == null ? null : message.getKey(); List<Serializable> localizedArguments = message == null ? null : (List<Serializable>) (List) message.getArgument(); // FIXME: brutal hack OperationResult opResult = new OperationResult( result.getOperation(), params, context, returns, OperationResultStatus.parseStatusType(result.getStatus()), result.getToken(), result.getMessageCode(), result.getMessage(), localizedMessage, localizedArguments, null, subresults); if (result.getCount() != null) { opResult.setCount(result.getCount()); } return opResult; } public OperationResultType createOperationResultType() { return createOperationResultType(this); } private OperationResultType createOperationResultType(OperationResult opResult) { OperationResultType result = new OperationResultType(); result.setToken(opResult.getToken()); result.setStatus(OperationResultStatus.createStatusType(opResult.getStatus())); if (opResult.getCount() != 1) { result.setCount(opResult.getCount()); } result.setOperation(opResult.getOperation()); result.setMessage(opResult.getMessage()); result.setMessageCode(opResult.getMessageCode()); if (opResult.getCause() != null || !opResult.details.isEmpty()) { StringBuilder detailsb = new StringBuilder(); // Record text messages in details (if present) if (!opResult.details.isEmpty()) { for (String line : opResult.details) { detailsb.append(line); detailsb.append("\n"); } } // Record stack trace in details if a cause is present if (opResult.getCause() != null) { Throwable ex = opResult.getCause(); detailsb.append(ex.getClass().getName()); detailsb.append(": "); detailsb.append(ex.getMessage()); detailsb.append("\n"); StackTraceElement[] stackTrace = ex.getStackTrace(); for (int i = 0; i < stackTrace.length; i++) { detailsb.append(stackTrace[i].toString()); detailsb.append("\n"); } } result.setDetails(detailsb.toString()); } if (StringUtils.isNotEmpty(opResult.getLocalizationMessage())) { LocalizedMessageType message = new LocalizedMessageType(); message.setKey(opResult.getLocalizationMessage()); if (opResult.getLocalizationArguments() != null) { message.getArgument().addAll(opResult.getLocalizationArguments()); } result.setLocalizedMessage(message); } // Set<Entry<String, Serializable>> params = opResult.getParams(); // if (!params.isEmpty()) { ParamsType paramsType = ParamsTypeUtil.toParamsType(opResult.getParams()); result.setParams(paramsType); // for (Entry<String, Serializable> entry : params) { // paramsType.getEntry().add(createEntryElement(entry.getKey(),entry.getValue())); // } // } // Set<Entry<String, Serializable>> context = opResult.getContext().entrySet(); // if (!context.isEmpty()) { paramsType = ParamsTypeUtil.toParamsType(opResult.getContext()); result.setContext(paramsType); // for (Entry<String, Serializable> entry : context) { // paramsType.getEntry().add(createEntryElement(entry.getKey(),entry.getValue())); // } // } // Set<Entry<String, Serializable>> returns = opResult.getReturns().entrySet(); // if (!returns.isEmpty()) { paramsType = ParamsTypeUtil.toParamsType(opResult.getReturns()); result.setReturns(paramsType); // for (Entry<String, Serializable> entry : returns) { // paramsType.getEntry().add(createEntryElement(entry.getKey(),entry.getValue())); // } // } for (OperationResult subResult : opResult.getSubresults()) { result.getPartialResults().add(opResult.createOperationResultType(subResult)); } return result; } // /** // * Temporary workaround, brutally hacked -- so that the conversion // * of OperationResult into OperationResultType 'somehow' works, at least to the point // * where when we: // * - have OR1 // * - serialize it into ORT1 // * - then deserialize into OR2 // * - serialize again into ORT2 // * so we get ORT1.equals(ORT2) - at least in our simple test case :) // * // * FIXME: this should be definitely reworked // * // * @param entry // * @return // */ // private EntryType createEntryElement(String key, Serializable value) { // EntryType entryType = new EntryType(); // entryType.setKey(key); // if (value != null) { // Document doc = DOMUtil.getDocument(); // if (value instanceof ObjectType && ((ObjectType)value).getOid() != null) { // // Store only reference on the OID. This is faster and getObject can be used to retrieve // // the object if needed. Although is does not provide 100% accuracy, it is a good tradeoff. // setObjectReferenceEntry(entryType, ((ObjectType)value)); // // these values should be put 'as they are', in order to be deserialized into themselves // } else if (value instanceof String || value instanceof Integer || value instanceof Long) { // entryType.setEntryValue(new JAXBElement<Serializable>(SchemaConstants.C_PARAM_VALUE, // Serializable.class, value)); // } else if (XmlTypeConverter.canConvert(value.getClass())) { //// try { //// entryType.setEntryValue(new JXmlTypeConverter.toXsdElement(value, // SchemaConstants.C_PARAM_VALUE, doc, true)); //// } catch (SchemaException e) { //// LOGGER.error("Cannot convert value {} to XML: {}",value,e.getMessage()); //// setUnknownJavaObjectEntry(entryType, value); //// } // } else if (value instanceof Element || value instanceof JAXBElement<?>) { // entryType.setEntryValue((JAXBElement<?>) value); // // FIXME: this is really bad code ... it means that 'our' JAXB object should be put as is // } else if // ("com.evolveum.midpoint.xml.ns._public.common.common_2".equals(value.getClass().getPackage().getName())) { // JAXBElement<Object> o = new JAXBElement<Object>(SchemaConstants.C_PARAM_VALUE, Object.class, // value); // entryType.setEntryValue(o); // } else { // setUnknownJavaObjectEntry(entryType, value); // } // } // return entryType; // } // // private void setObjectReferenceEntry(EntryType entryType, ObjectType objectType) { // ObjectReferenceType objRefType = new ObjectReferenceType(); // objRefType.setOid(objectType.getOid()); // ObjectTypes type = ObjectTypes.getObjectType(objectType.getClass()); // if (type != null) { // objRefType.setType(type.getTypeQName()); // } // JAXBElement<ObjectReferenceType> element = new JAXBElement<ObjectReferenceType>( // SchemaConstants.C_OBJECT_REF, ObjectReferenceType.class, objRefType); //// entryType.setAny(element); // } // // private void setUnknownJavaObjectEntry(EntryType entryType, Serializable value) { // UnknownJavaObjectType ujo = new UnknownJavaObjectType(); // ujo.setClazz(value.getClass().getName()); // ujo.setToString(value.toString()); // entryType.setEntryValue(new ObjectFactory().createUnknownJavaObject(ujo)); // } public void summarize() { Iterator<OperationResult> iterator = getSubresults().iterator(); while (iterator.hasNext()) { OperationResult subresult = iterator.next(); if (subresult.getCount() > 1) { // Already summarized continue; } if (subresult.isError() && summarizeErrors) { // go on } else if (subresult.isPartialError() && summarizePartialErrors) { // go on } else if (subresult.isSuccess() && summarizeSuccesses) { // go on } else { continue; } OperationResult similar = findSimilarSubresult(subresult); if (similar == null) { // Nothing to summarize to continue; } merge(similar, subresult); iterator.remove(); } // subresult stripping if necessary // we strip subresults that have same operation name and status, if there are more of them than // threshold Map<OperationStatusKey, Integer> counter = new HashMap<OperationStatusKey, Integer>(); iterator = getSubresults().iterator(); while (iterator.hasNext()) { OperationResult sr = iterator.next(); OperationStatusKey key = new OperationStatusKey(sr.getOperation(), sr.getStatus()); if (counter.containsKey(key)) { int count = counter.get(key); if (count > SUBRESULT_STRIP_THRESHOLD) { iterator.remove(); } else { counter.put(key, ++count); } } else { counter.put(key, 1); } } } private void merge(OperationResult target, OperationResult source) { mergeMap(target.getParams(), source.getParams()); mergeMap(target.getContext(), source.getContext()); mergeMap(target.getReturns(), source.getReturns()); target.incrementCount(); } private void mergeMap(Map<String, Serializable> targetMap, Map<String, Serializable> sourceMap) { for (Entry<String, Serializable> targetEntry : targetMap.entrySet()) { String targetKey = targetEntry.getKey(); Serializable targetValue = targetEntry.getValue(); if (targetValue != null && targetValue instanceof VariousValues) { continue; } Serializable sourceValue = sourceMap.get(targetKey); if (MiscUtil.equals(targetValue, sourceValue)) { // Entries match, nothing to do continue; } // Entries do not match. The target entry needs to be marked as VariousValues targetEntry.setValue(new VariousValues()); } for (Entry<String, Serializable> sourceEntry : sourceMap.entrySet()) { String sourceKey = sourceEntry.getKey(); if (!targetMap.containsKey(sourceKey)) { targetMap.put(sourceKey, new VariousValues()); } } } private OperationResult findSimilarSubresult(OperationResult subresult) { OperationResult similar = null; for (OperationResult sub : getSubresults()) { if (sub == subresult) { continue; } if (!sub.operation.equals(subresult.operation)) { continue; } if (sub.status != subresult.status) { continue; } if (!MiscUtil.equals(sub.message, subresult.message)) { continue; } if (similar == null || (similar.count < sub.count)) { similar = sub; } } return similar; } /** * Removes all the successful minor results. Also checks if the result is roughly consistent and * complete. (e.g. does not have unknown operation status, etc.) */ public void cleanupResult() { cleanupResult(null); } /** * Removes all the successful minor results. Also checks if the result is roughly consistent and * complete. (e.g. does not have unknown operation status, etc.) * * <p>The argument "e" is for easier use of the cleanup in the exceptions handlers. The original * exception is passed to the IAE that this method produces for easier debugging. */ public void cleanupResult(Throwable e) { if (status == OperationResultStatus.UNKNOWN) { LOGGER.error( "Attempt to cleanup result of operation " + operation + " that is still UNKNOWN:\n{}", this.debugDump()); throw new IllegalStateException( "Attempt to cleanup result of operation " + operation + " that is still UNKNOWN"); } if (subresults == null) { return; } Iterator<OperationResult> iterator = subresults.iterator(); while (iterator.hasNext()) { OperationResult subresult = iterator.next(); if (subresult.getStatus() == OperationResultStatus.UNKNOWN) { String message = "Subresult " + subresult.getOperation() + " of operation " + operation + " is still UNKNOWN during cleanup"; LOGGER.error("{}:\n{}", message, this.debugDump(), e); if (e == null) { throw new IllegalStateException(message); } else { throw new IllegalStateException(message + "; during handling of exception " + e, e); } } if (subresult.canCleanup()) { iterator.remove(); } } } private boolean canCleanup() { if (!minor) { return false; } return status == OperationResultStatus.SUCCESS || status == OperationResultStatus.NOT_APPLICABLE; } @Override public String debugDump() { return debugDump(0); } @Override public String debugDump(int indent) { StringBuilder sb = new StringBuilder(); dumpIndent(sb, indent, true); return sb.toString(); } public String dump(boolean withStack) { StringBuilder sb = new StringBuilder(); dumpIndent(sb, 0, withStack); return sb.toString(); } private void dumpIndent(StringBuilder sb, int indent, boolean printStackTrace) { for (int i = 0; i < indent; i++) { sb.append(INDENT_STRING); } sb.append("*op* "); sb.append(operation); sb.append(", st: "); sb.append(status); if (minor) { sb.append(", MINOR"); } sb.append(", msg: "); sb.append(message); if (count > 1) { sb.append(" x"); sb.append(count); } sb.append("\n"); for (Map.Entry<String, Serializable> entry : getParams().entrySet()) { for (int i = 0; i < indent + 2; i++) { sb.append(INDENT_STRING); } sb.append("[p]"); sb.append(entry.getKey()); sb.append("="); sb.append(dumpEntry(indent + 2, entry.getValue())); sb.append("\n"); } for (Map.Entry<String, Serializable> entry : getContext().entrySet()) { for (int i = 0; i < indent + 2; i++) { sb.append(INDENT_STRING); } sb.append("[c]"); sb.append(entry.getKey()); sb.append("="); sb.append(dumpEntry(indent + 2, entry.getValue())); sb.append("\n"); } for (Map.Entry<String, Serializable> entry : getReturns().entrySet()) { for (int i = 0; i < indent + 2; i++) { sb.append(INDENT_STRING); } sb.append("[r]"); sb.append(entry.getKey()); sb.append("="); sb.append(dumpEntry(indent + 2, entry.getValue())); sb.append("\n"); } for (String line : details) { for (int i = 0; i < indent + 2; i++) { sb.append(INDENT_STRING); } sb.append("[d]"); sb.append(line); sb.append("\n"); } if (cause != null) { for (int i = 0; i < indent + 2; i++) { sb.append(INDENT_STRING); } sb.append("[cause]"); sb.append(cause.getClass().getSimpleName()); sb.append(":"); sb.append(cause.getMessage()); sb.append("\n"); if (printStackTrace) { dumpStackTrace(sb, cause.getStackTrace(), indent + 4); dumpInnerCauses(sb, cause.getCause(), indent + 3); } } for (OperationResult sub : getSubresults()) { sub.dumpIndent(sb, indent + 1, printStackTrace); } } private String dumpEntry(int indent, Serializable value) { if (value instanceof Element) { Element element = (Element) value; if (SchemaConstants.C_VALUE.equals(DOMUtil.getQName(element))) { try { String cvalue = null; if (value == null) { cvalue = "null"; } else if (value instanceof Element) { cvalue = SchemaDebugUtil.prettyPrint(XmlTypeConverter.toJavaValue((Element) value)); } else { cvalue = SchemaDebugUtil.prettyPrint(value); } return DebugUtil.fixIndentInMultiline(indent, INDENT_STRING, cvalue); } catch (Exception e) { return DebugUtil.fixIndentInMultiline( indent, INDENT_STRING, "value: " + element.getTextContent()); } } } return DebugUtil.fixIndentInMultiline( indent, INDENT_STRING, SchemaDebugUtil.prettyPrint(value)); } private void dumpInnerCauses(StringBuilder sb, Throwable innerCause, int indent) { if (innerCause == null) { return; } for (int i = 0; i < indent; i++) { sb.append(INDENT_STRING); } sb.append("Caused by "); sb.append(innerCause.getClass().getName()); sb.append(": "); sb.append(innerCause.getMessage()); sb.append("\n"); dumpStackTrace(sb, innerCause.getStackTrace(), indent + 1); dumpInnerCauses(sb, innerCause.getCause(), indent); } private static void dumpStackTrace(StringBuilder sb, StackTraceElement[] stackTrace, int indent) { for (int i = 0; i < stackTrace.length; i++) { for (int j = 0; j < indent; j++) { sb.append(INDENT_STRING); } StackTraceElement element = stackTrace[i]; sb.append(element.toString()); sb.append("\n"); } } public void setBackgroundTaskOid(String oid) { addReturn(RETURN_BACKGROUND_TASK_OID, oid); } public String getBackgroundTaskOid() { Object oid = getReturns().get(RETURN_BACKGROUND_TASK_OID); return oid != null ? String.valueOf(oid) : null; } // primitive implementation - uncomment it if needed // public OperationResult clone() { // return CloneUtil.clone(this); // } private static class OperationStatusKey { private String operation; private OperationResultStatus status; private OperationStatusKey(String operation, OperationResultStatus status) { this.operation = operation; this.status = status; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; OperationStatusKey that = (OperationStatusKey) o; if (operation != null ? !operation.equals(that.operation) : that.operation != null) return false; if (status != that.status) return false; return true; } @Override public int hashCode() { int result = operation != null ? operation.hashCode() : 0; result = 31 * result + (status != null ? status.hashCode() : 0); return result; } } public OperationResult clone() { OperationResult clone = new OperationResult(operation); clone.status = status; clone.params = CloneUtil.clone(params); clone.context = CloneUtil.clone(context); clone.returns = CloneUtil.clone(returns); clone.token = token; clone.messageCode = messageCode; clone.message = message; clone.localizationMessage = localizationMessage; clone.localizationArguments = CloneUtil.clone(localizationArguments); clone.cause = CloneUtil.clone(cause); clone.count = count; if (subresults != null) { clone.subresults = new ArrayList<>(subresults.size()); for (OperationResult subresult : subresults) { if (subresult != null) { clone.subresults.add(subresult.clone()); } } } clone.details = CloneUtil.clone(details); clone.summarizeErrors = summarizeErrors; clone.summarizePartialErrors = summarizePartialErrors; clone.summarizeSuccesses = summarizeSuccesses; clone.minor = minor; return clone; } }
/** @author lazyman */ public final class RUtil { /** * This constant is used for mapping type for {@link javax.persistence.Lob} fields. {@link * org.hibernate.type.MaterializedClobType} was not working properly with PostgreSQL, causing TEXT * types (clobs) to be saved not in table row but somewhere else and it always messed up UTF-8 * encoding */ public static final String LOB_STRING_TYPE = "org.hibernate.type.StringClobType"; public static final int COLUMN_LENGTH_QNAME = 157; public static final String QNAME_DELIMITER = "#"; /** This constant is used for oid column size in database. */ public static final int COLUMN_LENGTH_OID = 36; /** This namespace is used for wrapping xml parts of objects during save to database. */ public static final String NS_SQL_REPO = "http://midpoint.evolveum.com/xml/ns/fake/sqlRepository-1.xsd"; public static final String SQL_REPO_OBJECT = "sqlRepoObject"; public static final QName CUSTOM_OBJECT = new QName(NS_SQL_REPO, SQL_REPO_OBJECT); private static final Trace LOGGER = TraceManager.getTrace(RUtil.class); private RUtil() {} public static <T extends Objectable> void revive(Objectable object, PrismContext prismContext) throws DtoTranslationException { try { prismContext.adopt(object); } catch (SchemaException ex) { throw new DtoTranslationException(ex.getMessage(), ex); } } public static <T> String toRepo( ItemDefinition parentDefinition, QName itemName, T value, PrismContext prismContext) throws SchemaException, JAXBException { if (value == null) { return null; } if (value instanceof Objectable) { return prismContext.serializeObjectToString( ((Objectable) value).asPrismObject(), PrismContext.LANG_XML); } ItemDefinition definition = null; if (parentDefinition instanceof PrismContainerDefinition) { definition = ((PrismContainerDefinition) parentDefinition).findItemDefinition(itemName); if (definition == null) { definition = parentDefinition; } } else { definition = parentDefinition; } return ValueSerializationUtil.serializeValue( value, definition, itemName, parentDefinition.getName(), prismContext, PrismContext.LANG_XML); } public static Element createFakeParentElement() { return DOMUtil.createElement(DOMUtil.getDocument(), CUSTOM_OBJECT); } public static <T> Set<T> listToSet(List<T> list) { if (list == null || list.isEmpty()) { return null; } return new HashSet<>(list); } public static Set<RPolyString> listPolyToSet(List<PolyStringType> list) { if (list == null || list.isEmpty()) { return null; } Set<RPolyString> set = new HashSet<>(); for (PolyStringType str : list) { set.add(RPolyString.copyFromJAXB(str)); } return set; } public static List<ObjectReferenceType> safeSetReferencesToList( Set<? extends RObjectReference> set, PrismContext prismContext) { if (set == null || set.isEmpty()) { return new ArrayList<>(); } List<ObjectReferenceType> list = new ArrayList<>(); for (RObjectReference str : set) { ObjectReferenceType ort = new ObjectReferenceType(); RObjectReference.copyToJAXB(str, ort, prismContext); list.add(ort); } return list; } public static Set safeListReferenceToSet( List<ObjectReferenceType> list, PrismContext prismContext, RObject owner, RReferenceOwner refOwner) { Set<RObjectReference> set = new HashSet<>(); if (list == null || list.isEmpty()) { return set; } for (ObjectReferenceType ref : list) { RObjectReference rRef = RUtil.jaxbRefToRepo(ref, prismContext, owner, refOwner); if (rRef != null) { set.add(rRef); } } return set; } public static RObjectReference jaxbRefToRepo( ObjectReferenceType reference, PrismContext prismContext, RObject owner, RReferenceOwner refOwner) { if (reference == null) { return null; } Validate.notNull(owner, "Owner of reference must not be null."); Validate.notNull(refOwner, "Reference owner of reference must not be null."); Validate.notEmpty(reference.getOid(), "Target oid reference must not be null."); RObjectReference repoRef = RReferenceOwner.createObjectReference(refOwner); repoRef.setOwner(owner); RObjectReference.copyFromJAXB(reference, repoRef, prismContext); return repoRef; } public static REmbeddedReference jaxbRefToEmbeddedRepoRef( ObjectReferenceType jaxb, PrismContext prismContext) { if (jaxb == null) { return null; } REmbeddedReference ref = new REmbeddedReference(); REmbeddedReference.copyFromJAXB(jaxb, ref, prismContext); return ref; } public static Integer getIntegerFromString(String val) { if (val == null || !val.matches("[0-9]+")) { return null; } return Integer.parseInt(val); } /** * This method is used to override "hasIdentifierMapper" in EntityMetaModels of entities which * have composite id and class defined for it. It's workaround for bug as found in forum * https://forum.hibernate.org/viewtopic.php?t=978915&highlight= * * @param sessionFactory */ public static void fixCompositeIDHandling(SessionFactory sessionFactory) { fixCompositeIdentifierInMetaModel(sessionFactory, RObjectDeltaOperation.class); fixCompositeIdentifierInMetaModel(sessionFactory, ROExtDate.class); fixCompositeIdentifierInMetaModel(sessionFactory, ROExtString.class); fixCompositeIdentifierInMetaModel(sessionFactory, ROExtPolyString.class); fixCompositeIdentifierInMetaModel(sessionFactory, ROExtReference.class); fixCompositeIdentifierInMetaModel(sessionFactory, ROExtLong.class); fixCompositeIdentifierInMetaModel(sessionFactory, RAssignmentExtension.class); fixCompositeIdentifierInMetaModel(sessionFactory, RAExtDate.class); fixCompositeIdentifierInMetaModel(sessionFactory, RAExtString.class); fixCompositeIdentifierInMetaModel(sessionFactory, RAExtPolyString.class); fixCompositeIdentifierInMetaModel(sessionFactory, RAExtReference.class); fixCompositeIdentifierInMetaModel(sessionFactory, RAExtLong.class); fixCompositeIdentifierInMetaModel(sessionFactory, RObjectReference.class); for (RReferenceOwner owner : RReferenceOwner.values()) { fixCompositeIdentifierInMetaModel(sessionFactory, owner.getClazz()); } fixCompositeIdentifierInMetaModel(sessionFactory, RAssignmentReference.class); for (RCReferenceOwner owner : RCReferenceOwner.values()) { fixCompositeIdentifierInMetaModel(sessionFactory, owner.getClazz()); } fixCompositeIdentifierInMetaModel(sessionFactory, RAssignment.class); fixCompositeIdentifierInMetaModel(sessionFactory, RExclusion.class); fixCompositeIdentifierInMetaModel(sessionFactory, RTrigger.class); for (RObjectType type : ClassMapper.getKnownTypes()) { fixCompositeIdentifierInMetaModel(sessionFactory, type.getClazz()); } } private static void fixCompositeIdentifierInMetaModel( SessionFactory sessionFactory, Class clazz) { ClassMetadata classMetadata = sessionFactory.getClassMetadata(clazz); if (classMetadata instanceof AbstractEntityPersister) { AbstractEntityPersister persister = (AbstractEntityPersister) classMetadata; EntityMetamodel model = persister.getEntityMetamodel(); IdentifierProperty identifier = model.getIdentifierProperty(); try { Field field = IdentifierProperty.class.getDeclaredField("hasIdentifierMapper"); field.setAccessible(true); field.set(identifier, true); field.setAccessible(false); } catch (Exception ex) { throw new SystemException( "Attempt to fix entity meta model with hack failed, reason: " + ex.getMessage(), ex); } } } public static void copyResultFromJAXB( ItemDefinition parentDef, QName itemName, OperationResultType jaxb, OperationResult repo, PrismContext prismContext) throws DtoTranslationException { Validate.notNull(repo, "Repo object must not be null."); if (jaxb == null) { return; } repo.setStatus(getRepoEnumValue(jaxb.getStatus(), ROperationResultStatus.class)); if (repo instanceof OperationResultFull) { try { ((OperationResultFull) repo) .setFullResult(RUtil.toRepo(parentDef, itemName, jaxb, prismContext)); } catch (Exception ex) { throw new DtoTranslationException(ex.getMessage(), ex); } } } public static String computeChecksum(Object... objects) { StringBuilder builder = new StringBuilder(); for (Object object : objects) { if (object == null) { continue; } builder.append(object.toString()); } return DigestUtils.md5Hex(builder.toString()); } public static <T extends SchemaEnum> T getRepoEnumValue(Object object, Class<T> type) { if (object == null) { return null; } Object[] values = type.getEnumConstants(); for (Object value : values) { T schemaEnum = (T) value; if (schemaEnum.getSchemaValue().equals(object)) { return schemaEnum; } } throw new IllegalArgumentException( "Unknown value '" + object + "' of type '" + object.getClass() + "', can't translate to '" + type + "'."); } public static String qnameToString(QName qname) { StringBuilder sb = new StringBuilder(); if (qname != null) { sb.append(qname.getNamespaceURI()); } sb.append(QNAME_DELIMITER); if (qname != null) { sb.append(qname.getLocalPart()); } return sb.toString(); } public static QName stringToQName(String text) { if (StringUtils.isEmpty(text)) { return null; } int index = text.lastIndexOf(QNAME_DELIMITER); String namespace = StringUtils.left(text, index); String localPart = StringUtils.right(text, text.length() - index - 1); if (StringUtils.isEmpty(localPart)) { return null; } return new QName(namespace, localPart); } public static Long toLong(Short s) { if (s == null) { return null; } return s.longValue(); } public static Short toShort(Long l) { if (l == null) { return null; } if (l > Short.MAX_VALUE || l < Short.MIN_VALUE) { throw new IllegalArgumentException("Couldn't cast value to short " + l); } return l.shortValue(); } public static String getDebugString(RObject object) { StringBuilder sb = new StringBuilder(); if (object.getName() != null) { sb.append(object.getName().getOrig()); } else { sb.append("null"); } sb.append('(').append(object.getOid()).append(')'); return sb.toString(); } public static String getTableName(Class hqlType) { MidPointNamingStrategy namingStrategy = new MidPointNamingStrategy(); return namingStrategy.classToTableName(hqlType.getSimpleName()); } public static byte[] getByteArrayFromXml(String xml, boolean compress) { byte[] array; GZIPOutputStream gzip = null; try { if (compress) { ByteArrayOutputStream out = new ByteArrayOutputStream(); gzip = new GZIPOutputStream(out); gzip.write(xml.getBytes("utf-8")); gzip.close(); out.close(); array = out.toByteArray(); } else { array = xml.getBytes("utf-8"); } } catch (Exception ex) { throw new SystemException("Couldn't save full xml object, reason: " + ex.getMessage(), ex); } finally { IOUtils.closeQuietly(gzip); } return array; } public static String getXmlFromByteArray(byte[] array, boolean compressed) { String xml; GZIPInputStream gzip = null; try { if (compressed) { ByteArrayOutputStream out = new ByteArrayOutputStream(); gzip = new GZIPInputStream(new ByteArrayInputStream(array)); IOUtils.copy(gzip, out); xml = new String(out.toByteArray(), "utf-8"); } else { xml = new String(array, "utf-8"); } } catch (Exception ex) { throw new SystemException( "Couldn't read data from full object column, reason: " + ex.getMessage(), ex); } finally { IOUtils.closeQuietly(gzip); } return xml; } public static OrgFilter findOrgFilter(ObjectQuery query) { return query != null ? findOrgFilter(query.getFilter()) : null; } public static OrgFilter findOrgFilter(ObjectFilter filter) { if (filter == null) { return null; } if (filter instanceof OrgFilter) { return (OrgFilter) filter; } if (filter instanceof LogicalFilter) { LogicalFilter logical = (LogicalFilter) filter; for (ObjectFilter f : logical.getConditions()) { OrgFilter o = findOrgFilter(f); if (o != null) { return o; } } } return null; } }
/** * Processor to handle everything about focus: values, assignments, etc. * * @author Radovan Semancik */ @Component public class FocusProcessor { private static final Trace LOGGER = TraceManager.getTrace(FocusProcessor.class); private PrismContainerDefinition<ActivationType> activationDefinition; @Autowired(required = true) private InboundProcessor inboundProcessor; @Autowired(required = true) private AssignmentProcessor assignmentProcessor; @Autowired(required = true) private ObjectTemplateProcessor objectTemplateProcessor; @Autowired(required = true) private MappingFactory mappingFactory; @Autowired(required = true) private PrismContext prismContext; @Autowired(required = true) private PasswordPolicyProcessor passwordPolicyProcessor; @Autowired(required = true) private ModelObjectResolver modelObjectResolver; @Autowired(required = true) private ActivationComputer activationComputer; @Autowired(required = true) private ExpressionFactory expressionFactory; @Autowired(required = true) @Qualifier("cacheRepositoryService") private transient RepositoryService cacheRepositoryService; @Autowired(required = true) private MappingEvaluationHelper mappingHelper; <O extends ObjectType, F extends FocusType> void processFocus( LensContext<O> context, String activityDescription, XMLGregorianCalendar now, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, PolicyViolationException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException { LensFocusContext<O> focusContext = context.getFocusContext(); if (focusContext == null) { return; } if (!FocusType.class.isAssignableFrom(focusContext.getObjectTypeClass())) { // We can do this only for FocusType objects. return; } LensContext<F> fContext = (LensContext<F>) context; LensFocusContext<F> fFocusContext = fContext.getFocusContext(); processFocusFocus((LensContext<F>) context, activityDescription, now, task, result); } private <F extends FocusType> void processFocusFocus( LensContext<F> context, String activityDescription, XMLGregorianCalendar now, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, PolicyViolationException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException { LensFocusContext<F> focusContext = context.getFocusContext(); ObjectTemplateType objectTemplate = context.getFocusTemplate(); boolean resetOnRename = true; // This is fixed now. TODO: make it configurable int maxIterations = 0; IterationSpecificationType iterationSpecificationType = null; if (objectTemplate != null) { iterationSpecificationType = objectTemplate.getIteration(); maxIterations = LensUtil.determineMaxIterations(iterationSpecificationType); } int iteration = focusContext.getIteration(); String iterationToken = focusContext.getIterationToken(); boolean wasResetIterationCounter = false; PrismObject<F> focusCurrent = focusContext.getObjectCurrent(); if (focusCurrent != null && iterationToken == null) { Integer focusIteration = focusCurrent.asObjectable().getIteration(); if (focusIteration != null) { iteration = focusIteration; } iterationToken = focusCurrent.asObjectable().getIterationToken(); } while (true) { ObjectTypeTemplateType objectPolicyConfigurationType = focusContext.getObjectPolicyConfigurationType(); if (objectPolicyConfigurationType != null && BooleanUtils.isTrue(objectPolicyConfigurationType.isOidNameBoundMode())) { // Generate the name now - unless it is already present PrismObject<F> focusNew = focusContext.getObjectNew(); if (focusNew != null) { PolyStringType focusNewName = focusNew.asObjectable().getName(); if (focusNewName == null) { String newName = focusNew.getOid(); if (newName == null) { newName = OidUtil.generateOid(); } LOGGER.trace("Generating new name (bound to OID): {}", newName); PrismObjectDefinition<F> focusDefinition = focusContext.getObjectDefinition(); PrismPropertyDefinition<PolyString> focusNameDef = focusDefinition.findPropertyDefinition(FocusType.F_NAME); PropertyDelta<PolyString> nameDelta = focusNameDef.createEmptyDelta(new ItemPath(FocusType.F_NAME)); nameDelta.setValueToReplace( new PrismPropertyValue<PolyString>( new PolyString(newName), OriginType.USER_POLICY, null)); focusContext.swallowToSecondaryDelta(nameDelta); focusContext.recompute(); } } } ExpressionVariables variables = Utils.getDefaultExpressionVariables( focusContext.getObjectNew(), null, null, null, context.getSystemConfiguration()); if (iterationToken == null) { iterationToken = LensUtil.formatIterationToken( context, focusContext, iterationSpecificationType, iteration, expressionFactory, variables, task, result); } // We have to remember the token and iteration in the context. // The context can be recomputed several times. But we always want // to use the same iterationToken if possible. If there is a random // part in the iterationToken expression that we need to avoid recomputing // the token otherwise the value can change all the time (even for the same inputs). // Storing the token in the secondary delta is not enough because secondary deltas can be // dropped // if the context is re-projected. focusContext.setIteration(iteration); focusContext.setIterationToken(iterationToken); LOGGER.trace( "Focus {} processing, iteration {}, token '{}'", new Object[] {focusContext.getHumanReadableName(), iteration, iterationToken}); String conflictMessage; if (!LensUtil.evaluateIterationCondition( context, focusContext, iterationSpecificationType, iteration, iterationToken, true, expressionFactory, variables, task, result)) { conflictMessage = "pre-iteration condition was false"; LOGGER.debug( "Skipping iteration {}, token '{}' for {} because the pre-iteration condition was false", new Object[] {iteration, iterationToken, focusContext.getHumanReadableName()}); } else { // INBOUND if (consistencyChecks) context.checkConsistence(); // Loop through the account changes, apply inbound expressions inboundProcessor.processInbound(context, now, task, result); if (consistencyChecks) context.checkConsistence(); context.recomputeFocus(); LensUtil.traceContext(LOGGER, activityDescription, "inbound", false, context, false); if (consistencyChecks) context.checkConsistence(); // ACTIVATION processActivation(context, now, result); // OBJECT TEMPLATE (before assignments) objectTemplateProcessor.processTemplate( context, ObjectTemplateMappingEvaluationPhaseType.BEFORE_ASSIGNMENTS, now, task, result); // ASSIGNMENTS assignmentProcessor.processAssignmentsProjections(context, now, task, result); assignmentProcessor.processOrgAssignments(context, result); context.recompute(); assignmentProcessor.checkForAssignmentConflicts(context, result); // OBJECT TEMPLATE (after assignments) objectTemplateProcessor.processTemplate( context, ObjectTemplateMappingEvaluationPhaseType.AFTER_ASSIGNMENTS, now, task, result); context.recompute(); // PASSWORD POLICY passwordPolicyProcessor.processPasswordPolicy(focusContext, context, result); // Processing done, check for success if (resetOnRename && !wasResetIterationCounter && willResetIterationCounter(focusContext)) { // Make sure this happens only the very first time during the first recompute. // Otherwise it will always change the token (especially if the token expression has a // random part) // hence the focusContext.getIterationToken() == null wasResetIterationCounter = true; if (iteration != 0) { iteration = 0; iterationToken = null; LOGGER.trace("Resetting iteration counter and token because rename was detected"); cleanupContext(focusContext); continue; } } PrismObject<F> previewObjectNew = focusContext.getObjectNew(); if (previewObjectNew == null) { // this must be delete } else { // Explicitly check for name. The checker would check for this also. But checking it here // will produce better error message PolyStringType objectName = previewObjectNew.asObjectable().getName(); if (objectName == null || objectName.getOrig().isEmpty()) { throw new SchemaException( "No name in new object " + objectName + " as produced by template " + objectTemplate + " in iteration " + iteration + ", we cannot process an object without a name"); } } // Check if iteration constraints are OK FocusConstraintsChecker<F> checker = new FocusConstraintsChecker<>(); checker.setPrismContext(prismContext); checker.setContext(context); checker.setRepositoryService(cacheRepositoryService); checker.check(previewObjectNew, result); if (checker.isSatisfiesConstraints()) { LOGGER.trace( "Current focus satisfies uniqueness constraints. Iteration {}, token '{}'", iteration, iterationToken); if (LensUtil.evaluateIterationCondition( context, focusContext, iterationSpecificationType, iteration, iterationToken, false, expressionFactory, variables, task, result)) { // stop the iterations break; } else { conflictMessage = "post-iteration condition was false"; LOGGER.debug( "Skipping iteration {}, token '{}' for {} because the post-iteration condition was false", new Object[] {iteration, iterationToken, focusContext.getHumanReadableName()}); } } else { LOGGER.trace( "Current focus does not satisfy constraints. Conflicting object: {}; iteration={}, maxIterations={}", new Object[] {checker.getConflictingObject(), iteration, maxIterations}); conflictMessage = checker.getMessages(); } if (!wasResetIterationCounter) { wasResetIterationCounter = true; if (iteration != 0) { iterationToken = null; iteration = 0; LOGGER.trace("Resetting iteration counter and token after conflict"); cleanupContext(focusContext); continue; } } } // Next iteration iteration++; iterationToken = null; if (iteration > maxIterations) { StringBuilder sb = new StringBuilder(); if (iteration == 1) { sb.append("Error processing "); } else { sb.append("Too many iterations (" + iteration + ") for "); } sb.append(focusContext.getHumanReadableName()); if (iteration == 1) { sb.append(": constraint violation: "); } else { sb.append(": cannot determine values that satisfy constraints: "); } if (conflictMessage != null) { sb.append(conflictMessage); } throw new ObjectAlreadyExistsException(sb.toString()); } cleanupContext(focusContext); } addIterationTokenDeltas(focusContext, iteration, iterationToken); if (consistencyChecks) context.checkConsistence(); } private <F extends FocusType> boolean willResetIterationCounter(LensFocusContext<F> focusContext) throws SchemaException { ObjectDelta<F> focusDelta = focusContext.getDelta(); if (focusDelta == null) { return false; } if (focusContext.isAdd() || focusContext.isDelete()) { return false; } if (focusDelta.findPropertyDelta(FocusType.F_ITERATION) != null) { // there was a reset already in previous projector runs return false; } // Check for rename PropertyDelta<Object> nameDelta = focusDelta.findPropertyDelta(new ItemPath(FocusType.F_NAME)); return nameDelta != null; } /** Remove the intermediate results of values processing such as secondary deltas. */ private <F extends FocusType> void cleanupContext(LensFocusContext<F> focusContext) throws SchemaException { // We must NOT clean up activation computation. This has happened before, it will not happen // again // and it does not depend on iteration LOGGER.trace("Cleaning up focus context"); focusContext.setProjectionWaveSecondaryDelta(null); focusContext.clearIntermediateResults(); focusContext.recompute(); } private <F extends FocusType> void processActivation( LensContext<F> context, XMLGregorianCalendar now, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, PolicyViolationException { LensFocusContext<F> focusContext = context.getFocusContext(); if (focusContext.isDelete()) { LOGGER.trace("Skipping processing of focus activation: focus delete"); return; } TimeIntervalStatusType validityStatusNew = null; TimeIntervalStatusType validityStatusOld = null; XMLGregorianCalendar validityChangeTimestamp = null; ActivationType activationNew = null; ActivationType activationOld = null; PrismObject<F> focusNew = focusContext.getObjectNew(); if (focusNew != null) { activationNew = focusNew.asObjectable().getActivation(); if (activationNew != null) { validityStatusNew = activationComputer.getValidityStatus(activationNew, now); validityChangeTimestamp = activationNew.getValidityChangeTimestamp(); } } PrismObject<F> focusOld = focusContext.getObjectOld(); if (focusOld != null) { activationOld = focusOld.asObjectable().getActivation(); if (activationOld != null) { validityStatusOld = activationComputer.getValidityStatus(activationOld, validityChangeTimestamp); } } if (validityStatusOld == validityStatusNew) { // No change, (almost) no work if (validityStatusNew != null && activationNew.getValidityStatus() == null) { // There was no validity change. But the status is not recorded. So let's record it so it // can be used in searches. recordValidityDelta(focusContext, validityStatusNew, now); } else { LOGGER.trace( "Skipping validity processing because there was no change ({} -> {})", validityStatusOld, validityStatusNew); } } else { LOGGER.trace("Validity change {} -> {}", validityStatusOld, validityStatusNew); recordValidityDelta(focusContext, validityStatusNew, now); } ActivationStatusType effectiveStatusNew = activationComputer.getEffectiveStatus( activationNew, validityStatusNew, ActivationStatusType.DISABLED); ActivationStatusType effectiveStatusOld = activationComputer.getEffectiveStatus( activationOld, validityStatusOld, ActivationStatusType.DISABLED); if (effectiveStatusOld == effectiveStatusNew) { // No change, (almost) no work if (effectiveStatusNew != null && (activationNew == null || activationNew.getEffectiveStatus() == null)) { // There was no effective status change. But the status is not recorded. So let's record it // so it can be used in searches. recordEffectiveStatusDelta(focusContext, effectiveStatusNew, now); } else { if (focusContext.getPrimaryDelta() != null && focusContext .getPrimaryDelta() .hasItemDelta(SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS)) { LOGGER.trace( "Forcing effective status delta even though there was no change ({} -> {}) because there is explicit administrativeStatus delta", effectiveStatusOld, effectiveStatusNew); // We need this to force the change down to the projections later in the activation // processor // some of the mappings will use effectiveStatus as a source, therefore there has to be a // delta for the mapping to work correctly recordEffectiveStatusDelta(focusContext, effectiveStatusNew, now); } else { LOGGER.trace( "Skipping effective status processing because there was no change ({} -> {})", effectiveStatusOld, effectiveStatusNew); } } } else { LOGGER.trace("Effective status change {} -> {}", effectiveStatusOld, effectiveStatusNew); recordEffectiveStatusDelta(focusContext, effectiveStatusNew, now); } } private <F extends ObjectType> void recordValidityDelta( LensFocusContext<F> focusContext, TimeIntervalStatusType validityStatusNew, XMLGregorianCalendar now) throws SchemaException { PrismContainerDefinition<ActivationType> activationDefinition = getActivationDefinition(); PrismPropertyDefinition<TimeIntervalStatusType> validityStatusDef = activationDefinition.findPropertyDefinition(ActivationType.F_VALIDITY_STATUS); PropertyDelta<TimeIntervalStatusType> validityStatusDelta = validityStatusDef.createEmptyDelta( new ItemPath(UserType.F_ACTIVATION, ActivationType.F_VALIDITY_STATUS)); if (validityStatusNew == null) { validityStatusDelta.setValueToReplace(); } else { validityStatusDelta.setValueToReplace( new PrismPropertyValue<TimeIntervalStatusType>( validityStatusNew, OriginType.USER_POLICY, null)); } focusContext.swallowToProjectionWaveSecondaryDelta(validityStatusDelta); PrismPropertyDefinition<XMLGregorianCalendar> validityChangeTimestampDef = activationDefinition.findPropertyDefinition(ActivationType.F_VALIDITY_CHANGE_TIMESTAMP); PropertyDelta<XMLGregorianCalendar> validityChangeTimestampDelta = validityChangeTimestampDef.createEmptyDelta( new ItemPath(UserType.F_ACTIVATION, ActivationType.F_VALIDITY_CHANGE_TIMESTAMP)); validityChangeTimestampDelta.setValueToReplace( new PrismPropertyValue<XMLGregorianCalendar>(now, OriginType.USER_POLICY, null)); focusContext.swallowToProjectionWaveSecondaryDelta(validityChangeTimestampDelta); } private <F extends ObjectType> void recordEffectiveStatusDelta( LensFocusContext<F> focusContext, ActivationStatusType effectiveStatusNew, XMLGregorianCalendar now) throws SchemaException { PrismContainerDefinition<ActivationType> activationDefinition = getActivationDefinition(); PrismPropertyDefinition<ActivationStatusType> effectiveStatusDef = activationDefinition.findPropertyDefinition(ActivationType.F_EFFECTIVE_STATUS); PropertyDelta<ActivationStatusType> effectiveStatusDelta = effectiveStatusDef.createEmptyDelta( new ItemPath(UserType.F_ACTIVATION, ActivationType.F_EFFECTIVE_STATUS)); effectiveStatusDelta.setValueToReplace( new PrismPropertyValue<ActivationStatusType>( effectiveStatusNew, OriginType.USER_POLICY, null)); focusContext.swallowToProjectionWaveSecondaryDelta(effectiveStatusDelta); PropertyDelta<XMLGregorianCalendar> timestampDelta = LensUtil.createActivationTimestampDelta( effectiveStatusNew, now, activationDefinition, OriginType.USER_POLICY); focusContext.swallowToProjectionWaveSecondaryDelta(timestampDelta); } private PrismContainerDefinition<ActivationType> getActivationDefinition() { if (activationDefinition == null) { ComplexTypeDefinition focusDefinition = prismContext.getSchemaRegistry().findComplexTypeDefinition(FocusType.COMPLEX_TYPE); activationDefinition = focusDefinition.findContainerDefinition(FocusType.F_ACTIVATION); } return activationDefinition; } /** Adds deltas for iteration and iterationToken to the focus if needed. */ private <F extends FocusType> void addIterationTokenDeltas( LensFocusContext<F> focusContext, int iteration, String iterationToken) throws SchemaException { PrismObject<F> objectCurrent = focusContext.getObjectCurrent(); if (objectCurrent != null) { Integer iterationOld = objectCurrent.asObjectable().getIteration(); String iterationTokenOld = objectCurrent.asObjectable().getIterationToken(); if (iterationOld != null && iterationOld == iteration && iterationTokenOld != null && iterationTokenOld.equals(iterationToken)) { // Already stored return; } } PrismObjectDefinition<F> objDef = focusContext.getObjectDefinition(); PrismPropertyValue<Integer> iterationVal = new PrismPropertyValue<Integer>(iteration); iterationVal.setOriginType(OriginType.USER_POLICY); PropertyDelta<Integer> iterationDelta = PropertyDelta.createReplaceDelta(objDef, FocusType.F_ITERATION, iterationVal); focusContext.swallowToSecondaryDelta(iterationDelta); PrismPropertyValue<String> iterationTokenVal = new PrismPropertyValue<String>(iterationToken); iterationTokenVal.setOriginType(OriginType.USER_POLICY); PropertyDelta<String> iterationTokenDelta = PropertyDelta.createReplaceDelta(objDef, FocusType.F_ITERATION_TOKEN, iterationTokenVal); focusContext.swallowToSecondaryDelta(iterationTokenDelta); } }
/** * @author lazyman * @author mserbak */ @PageDescriptor( url = "/admin/config/import", action = { @AuthorizationAction( actionUri = PageAdminConfiguration.AUTH_CONFIGURATION_ALL, label = PageAdminConfiguration.AUTH_CONFIGURATION_ALL_LABEL, description = PageAdminConfiguration.AUTH_CONFIGURATION_ALL_DESCRIPTION), @AuthorizationAction( actionUri = AuthorizationConstants.AUTZ_UI_CONFIGURATION_IMPORT_URL, label = "PageImportObject.auth.configImport.label", description = "PageImportObject.auth.configImport.description") }) public class PageImportObject extends PageAdminConfiguration { private static final Trace LOGGER = TraceManager.getTrace(PageImportObject.class); private static final String DOT_CLASS = PageImportObject.class.getName() + "."; private static final String OPERATION_IMPORT_FILE = DOT_CLASS + "importFile"; private static final String OPERATION_IMPORT_XML = DOT_CLASS + "importXml"; private static final String ID_MAIN_FORM = "mainForm"; private static final String ID_BUTTON_BAR = "buttonBar"; private static final String ID_IMPORT_OPTIONS = "importOptions"; private static final String ID_IMPORT_RADIO_GROUP = "importRadioGroup"; private static final String ID_FILE_RADIO = "fileRadio"; private static final String ID_XML_RADIO = "xmlRadio"; private static final String ID_BACK_BUTTON = "back"; private static final String ID_IMPORT_FILE_BUTTON = "importFileButton"; private static final String ID_IMPORT_XML_BUTTON = "importXmlButton"; private static final String ID_INPUT = "input"; private static final String ID_INPUT_ACE = "inputAce"; private static final String ID_ACE_EDITOR = "aceEditor"; private static final String ID_INPUT_FILE_LABEL = "inputFileLabel"; private static final String ID_INPUT_FILE = "inputFile"; private static final String ID_FILE_INPUT = "fileInput"; public static final String FROM_MENU_ITEM_PARAM = "openedFromMenuItem"; public static final String FROM_MENU_ITEM_PARAM_TRUE_VALUE = "1"; public static final String FROM_MENU_ITEM_PARAM_FALSE_VALUE = "0"; private static final Integer INPUT_FILE = 1; private static final Integer INPUT_XML = 2; private LoadableModel<ImportOptionsType> model; private IModel<String> xmlEditorModel; public PageImportObject() { model = new LoadableModel<ImportOptionsType>(false) { @Override protected ImportOptionsType load() { return MiscSchemaUtil.getDefaultImportOptions(); } }; xmlEditorModel = new Model<String>(null); initLayout(); } private void initLayout() { Form mainForm = new Form(ID_MAIN_FORM); add(mainForm); ImportOptionsPanel importOptions = new ImportOptionsPanel(ID_IMPORT_OPTIONS, model); mainForm.add(importOptions); final WebMarkupContainer input = new WebMarkupContainer(ID_INPUT); input.setOutputMarkupId(true); mainForm.add(input); final WebMarkupContainer buttonBar = new WebMarkupContainer(ID_BUTTON_BAR); buttonBar.setOutputMarkupId(true); mainForm.add(buttonBar); final IModel<Integer> groupModel = new Model<Integer>(INPUT_FILE); RadioGroup importRadioGroup = new RadioGroup(ID_IMPORT_RADIO_GROUP, groupModel); importRadioGroup.add( new AjaxFormChoiceComponentUpdatingBehavior() { @Override protected void onUpdate(AjaxRequestTarget target) { target.add(input); target.add(buttonBar); } }); mainForm.add(importRadioGroup); Radio fileRadio = new Radio(ID_FILE_RADIO, new Model(INPUT_FILE), importRadioGroup); importRadioGroup.add(fileRadio); Radio xmlRadio = new Radio(ID_XML_RADIO, new Model(INPUT_XML), importRadioGroup); importRadioGroup.add(xmlRadio); WebMarkupContainer inputAce = new WebMarkupContainer(ID_INPUT_ACE); addVisibileForInputType(inputAce, INPUT_XML, groupModel); input.add(inputAce); AceEditor aceEditor = new AceEditor(ID_ACE_EDITOR, xmlEditorModel); aceEditor.setOutputMarkupId(true); inputAce.add(aceEditor); WebMarkupContainer inputFileLabel = new WebMarkupContainer(ID_INPUT_FILE_LABEL); addVisibileForInputType(inputFileLabel, INPUT_FILE, groupModel); input.add(inputFileLabel); WebMarkupContainer inputFile = new WebMarkupContainer(ID_INPUT_FILE); addVisibileForInputType(inputFile, INPUT_FILE, groupModel); input.add(inputFile); FileUploadField fileInput = new FileUploadField(ID_FILE_INPUT); inputFile.add(fileInput); initButtons(buttonBar, groupModel); } private void addVisibileForInputType( Component comp, final Integer type, final IModel<Integer> groupModel) { comp.add( new VisibleEnableBehaviour() { @Override public boolean isVisible() { return type.equals(groupModel.getObject()); } }); } private void initButtons(WebMarkupContainer buttonBar, IModel<Integer> inputType) { AjaxButton backButton = new AjaxButton(ID_BACK_BUTTON, createStringResource("PageCertCampaign.button.back")) { @Override public void onClick(AjaxRequestTarget target) { redirectBack(); } }; backButton.add( new VisibleEnableBehaviour() { public boolean isVisible() { PageParameters params = PageImportObject.this.getPageParameters(); if (params != null) { if (params.get(FROM_MENU_ITEM_PARAM) != null && !params.get(FROM_MENU_ITEM_PARAM).isNull() && params .get(FROM_MENU_ITEM_PARAM) .toString() .equals(FROM_MENU_ITEM_PARAM_TRUE_VALUE)) { return false; } } return true; } }); buttonBar.add(backButton); AjaxSubmitButton saveFileButton = new AjaxSubmitButton( ID_IMPORT_FILE_BUTTON, createStringResource("PageImportObject.button.import")) { @Override protected void onSubmit(AjaxRequestTarget target, Form<?> form) { savePerformed(false, OPERATION_IMPORT_FILE, target); } @Override protected void onError(AjaxRequestTarget target, Form<?> form) { target.add(getFeedbackPanel()); } }; addVisibileForInputType(saveFileButton, INPUT_FILE, inputType); buttonBar.add(saveFileButton); AjaxSubmitButton saveXmlButton = new AjaxSubmitButton( ID_IMPORT_XML_BUTTON, createStringResource("PageImportObject.button.import")) { @Override protected void onSubmit(AjaxRequestTarget target, Form<?> form) { savePerformed(true, OPERATION_IMPORT_XML, target); } @Override protected void onError(AjaxRequestTarget target, Form<?> form) { target.add(getFeedbackPanel()); } }; addVisibileForInputType(saveXmlButton, INPUT_XML, inputType); buttonBar.add(saveXmlButton); } private FileUpload getUploadedFile() { FileUploadField file = (FileUploadField) get(createComponentPath(ID_MAIN_FORM, ID_INPUT, ID_INPUT_FILE, ID_FILE_INPUT)); return file.getFileUpload(); } private boolean validateInput(boolean raw) { if (raw) { return StringUtils.isNotEmpty(xmlEditorModel.getObject()); } return getUploadedFile() != null; } private InputStream getInputStream(boolean raw) throws Exception { if (raw) { return IOUtils.toInputStream(xmlEditorModel.getObject(), "utf-8"); } File newFile = null; try { // Create new file MidPointApplication application = getMidpointApplication(); WebApplicationConfiguration config = application.getWebApplicationConfiguration(); File folder = new File(config.getImportFolder()); if (!folder.exists() || !folder.isDirectory()) { folder.mkdir(); } FileUpload uploadedFile = getUploadedFile(); newFile = new File(folder, uploadedFile.getClientFileName()); // Check new file, delete if it already exists if (newFile.exists()) { newFile.delete(); } // Save file newFile.createNewFile(); uploadedFile.writeTo(newFile); InputStreamReader reader = new InputStreamReader(new FileInputStream(newFile), "utf-8"); return new ReaderInputStream(reader, reader.getEncoding()); } finally { if (newFile != null) { FileUtils.deleteQuietly(newFile); } } } private void clearOldFeedback() { getSession().getFeedbackMessages().clear(); getFeedbackMessages().clear(); } private void savePerformed(boolean raw, String operationName, AjaxRequestTarget target) { clearOldFeedback(); OperationResult result = new OperationResult(operationName); if (!validateInput(raw)) { error(getString("pageImportObject.message.nullFile")); target.add(getFeedbackPanel()); return; } InputStream stream = null; try { Task task = createSimpleTask(operationName); stream = getInputStream(raw); getModelService().importObjectsFromStream(stream, model.getObject(), task, result); result.recomputeStatus(); } catch (Exception ex) { result.recordFatalError("Couldn't import file.", ex); LoggingUtils.logUnexpectedException(LOGGER, "Couldn't import file", ex); } finally { if (stream != null) { IOUtils.closeQuietly(stream); } } showResult(result); target.add(PageImportObject.this); } }
/** @author lazyman */ @PageDescriptor( url = {"/admin/dashboard", "/admin"}, action = { @AuthorizationAction( actionUri = PageAdminHome.AUTH_HOME_ALL_URI, label = PageAdminHome.AUTH_HOME_ALL_LABEL, description = PageAdminHome.AUTH_HOME_ALL_DESCRIPTION), @AuthorizationAction( actionUri = AuthorizationConstants.AUTZ_UI_DASHBOARD_URL, label = "PageDashboard.auth.dashboard.label", description = "PageDashboard.auth.dashboard.description") }) public class PageDashboard extends PageAdminHome { private static final Trace LOGGER = TraceManager.getTrace(PageDashboard.class); private static final String DOT_CLASS = PageDashboard.class.getName() + "."; private static final String OPERATION_LOAD_ACCOUNTS = DOT_CLASS + "loadAccounts"; private static final String OPERATION_LOAD_ASSIGNMENTS = DOT_CLASS + "loadAssignments"; private static final String ID_PERSONAL_INFO = "personalInfo"; private static final String ID_ACCOUNTS = "accounts"; private static final String ID_ASSIGNMENTS = "assignments"; private static final String ID_SYSTEM_INFO = "systemInfo"; private final Model<PrismObject<UserType>> principalModel = new Model<PrismObject<UserType>>(); public PageDashboard() { principalModel.setObject(loadUserSelf(PageDashboard.this)); initLayout(); } private void initLayout() { initPersonalInfo(); initMyAccounts(); initAssignments(); initSystemInfo(); } private AccountCallableResult<List<SimpleAccountDto>> loadAccounts() throws Exception { LOGGER.debug("Loading accounts."); AccountCallableResult callableResult = new AccountCallableResult(); List<SimpleAccountDto> list = new ArrayList<SimpleAccountDto>(); callableResult.setValue(list); PrismObject<UserType> user = principalModel.getObject(); if (user == null) { return callableResult; } Task task = createSimpleTask(OPERATION_LOAD_ACCOUNTS); OperationResult result = task.getResult(); callableResult.setResult(result); Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection( ShadowType.F_RESOURCE, GetOperationOptions.createResolve()); List<ObjectReferenceType> references = user.asObjectable().getLinkRef(); for (ObjectReferenceType reference : references) { PrismObject<ShadowType> account = WebModelUtils.loadObject( ShadowType.class, reference.getOid(), options, this, task, result); if (account == null) { continue; } ShadowType accountType = account.asObjectable(); OperationResultType fetchResult = accountType.getFetchResult(); if (fetchResult != null) { callableResult.getFetchResults().add(OperationResult.createOperationResult(fetchResult)); } ResourceType resource = accountType.getResource(); String resourceName = WebMiscUtil.getName(resource); list.add( new SimpleAccountDto( WebMiscUtil.getOrigStringFromPoly(accountType.getName()), resourceName)); } result.recordSuccessIfUnknown(); result.recomputeStatus(); LOGGER.debug("Finished accounts loading."); return callableResult; } private void initPersonalInfo() { DashboardPanel personalInfo = new DashboardPanel( ID_PERSONAL_INFO, null, createStringResource("PageDashboard.personalInfo"), "fa fa-fw fa-male", DashboardColor.GRAY) { @Override protected Component getMainComponent(String componentId) { return new PersonalInfoPanel(componentId); } }; add(personalInfo); } private void initSystemInfo() { DashboardPanel systemInfo = new DashboardPanel( ID_SYSTEM_INFO, null, createStringResource("PageDashboard.systemInfo"), "fa fa-tachometer", DashboardColor.GREEN) { @Override protected Component getMainComponent(String componentId) { return new SystemInfoPanel(componentId); } }; add(systemInfo); } private void initMyAccounts() { AsyncDashboardPanel<Object, List<SimpleAccountDto>> accounts = new AsyncDashboardPanel<Object, List<SimpleAccountDto>>( ID_ACCOUNTS, createStringResource("PageDashboard.accounts"), "fa fa-fw fa-external-link", DashboardColor.BLUE) { @Override protected SecurityContextAwareCallable<CallableResult<List<SimpleAccountDto>>> createCallable(Authentication auth, IModel<Object> callableParameterModel) { return new SecurityContextAwareCallable<CallableResult<List<SimpleAccountDto>>>( getSecurityEnforcer(), auth) { @Override public AccountCallableResult<List<SimpleAccountDto>> callWithContextPrepared() throws Exception { return loadAccounts(); } }; } @Override protected Component getMainComponent(String markupId) { return new MyAccountsPanel( markupId, new PropertyModel<List<SimpleAccountDto>>(getModel(), CallableResult.F_VALUE)); } @Override protected void onPostSuccess(AjaxRequestTarget target) { showFetchResult(); super.onPostSuccess(target); } @Override protected void onUpdateError(AjaxRequestTarget target, Exception ex) { showFetchResult(); super.onUpdateError(target, ex); } private void showFetchResult() { AccountCallableResult<List<SimpleAccountDto>> result = (AccountCallableResult<List<SimpleAccountDto>>) getModel().getObject(); PageBase page = (PageBase) getPage(); for (OperationResult res : result.getFetchResults()) { if (!WebMiscUtil.isSuccessOrHandledError(res)) { page.showResult(res); } } } }; add(accounts); } private void initAssignments() { AsyncDashboardPanel<Object, List<AssignmentItemDto>> assignedOrgUnits = new AsyncDashboardPanel<Object, List<AssignmentItemDto>>( ID_ASSIGNMENTS, createStringResource("PageDashboard.assignments"), "fa fa-fw fa-star", DashboardColor.YELLOW) { @Override protected SecurityContextAwareCallable<CallableResult<List<AssignmentItemDto>>> createCallable(Authentication auth, IModel callableParameterModel) { return new SecurityContextAwareCallable<CallableResult<List<AssignmentItemDto>>>( getSecurityEnforcer(), auth) { @Override public CallableResult<List<AssignmentItemDto>> callWithContextPrepared() throws Exception { return loadAssignments(); } }; } @Override protected Component getMainComponent(String markupId) { return new MyAssignmentsPanel( markupId, new PropertyModel<List<AssignmentItemDto>>(getModel(), CallableResult.F_VALUE)); } }; add(assignedOrgUnits); } private CallableResult<List<AssignmentItemDto>> loadAssignments() throws Exception { LOGGER.debug("Loading assignments."); CallableResult callableResult = new CallableResult(); List<AssignmentItemDto> list = new ArrayList<AssignmentItemDto>(); callableResult.setValue(list); PrismObject<UserType> user = principalModel.getObject(); if (user == null || user.findContainer(UserType.F_ASSIGNMENT) == null) { return callableResult; } Task task = createSimpleTask(OPERATION_LOAD_ASSIGNMENTS); OperationResult result = task.getResult(); callableResult.setResult(result); PrismContainer assignments = user.findContainer(UserType.F_ASSIGNMENT); List<PrismContainerValue> values = assignments.getValues(); for (PrismContainerValue assignment : values) { AssignmentItemDto item = createAssignmentItem(user, assignment, task, result); if (item != null) { list.add(item); } } result.recordSuccessIfUnknown(); result.recomputeStatus(); Collections.sort(list); LOGGER.debug("Finished assignments loading."); return callableResult; } private AssignmentItemDto createAssignmentItem( PrismObject<UserType> user, PrismContainerValue assignment, Task task, OperationResult result) { PrismReference targetRef = assignment.findReference(AssignmentType.F_TARGET_REF); if (targetRef == null || targetRef.isEmpty()) { // account construction PrismContainer construction = assignment.findContainer(AssignmentType.F_CONSTRUCTION); String name = null; String description = null; if (construction.getValue().asContainerable() != null && !construction.isEmpty()) { ConstructionType constr = (ConstructionType) construction.getValue().asContainerable(); description = (String) construction.getPropertyRealValue(ConstructionType.F_DESCRIPTION, String.class); if (constr.getResourceRef() != null) { ObjectReferenceType resourceRef = constr.getResourceRef(); PrismObject resource = WebModelUtils.loadObject( ResourceType.class, resourceRef.getOid(), this, task, result); name = WebMiscUtil.getName(resource); } } return new AssignmentItemDto( AssignmentEditorDtoType.ACCOUNT_CONSTRUCTION, name, description, null); } PrismReferenceValue refValue = targetRef.getValue(); PrismObject value = refValue.getObject(); if (value == null) { // resolve reference value = WebModelUtils.loadObject(ObjectType.class, refValue.getOid(), this, task, result); } if (value == null) { // we couldn't resolve assignment details return new AssignmentItemDto(null, null, null, null); } String name = WebMiscUtil.getName(value); AssignmentEditorDtoType type = AssignmentEditorDtoType.getType(value.getCompileTimeClass()); String relation = refValue.getRelation() != null ? refValue.getRelation().getLocalPart() : null; String description = null; if (RoleType.class.isAssignableFrom(value.getCompileTimeClass())) { description = (String) value.getPropertyRealValue(RoleType.F_DESCRIPTION, String.class); } return new AssignmentItemDto(type, name, description, relation); } @Override public PageBase reinitialize() { return new PageDashboard(); } }
/** @author mserbak */ @PageDescriptor(url = "/login") public class PageLogin extends PageBase { private static final long serialVersionUID = 1L; private static final Trace LOGGER = TraceManager.getTrace(PageLogin.class); private static final String ID_FORGET_PASSWORD = "******"; private static final String ID_SELF_REGISTRATION = "selfRegistration"; private static final String DOT_CLASS = PageLogin.class.getName() + "."; protected static final String OPERATION_LOAD_RESET_PASSWORD_POLICY = DOT_CLASS + "loadPasswordResetPolicy"; private static final String OPERATION_LOAD_REGISTRATION_POLICY = DOT_CLASS + "loadRegistrationPolicy"; public PageLogin() { if (SecurityUtils.getPrincipalUser() != null) { MidPointApplication app = getMidpointApplication(); setResponsePage(app.getHomePage()); } BookmarkablePageLink<String> link = new BookmarkablePageLink<>(ID_FORGET_PASSWORD, PageForgotPassword.class); link.add( new VisibleEnableBehaviour() { private static final long serialVersionUID = 1L; @Override public boolean isVisible() { OperationResult parentResult = new OperationResult(OPERATION_LOAD_RESET_PASSWORD_POLICY); SecurityPolicyType securityPolicy = null; try { securityPolicy = getModelInteractionService().getSecurityPolicy(null, null, parentResult); } catch (ObjectNotFoundException | SchemaException e) { LOGGER.warn("Cannot read credentials policy: " + e.getMessage(), e); } boolean linkIsVisible = false; if (securityPolicy == null) { return linkIsVisible; } CredentialsPolicyType creds = securityPolicy.getCredentials(); if (creds != null && ((creds.getSecurityQuestions() != null && creds.getSecurityQuestions().getQuestionNumber() != null) || (securityPolicy.getCredentialsReset() != null))) { linkIsVisible = true; } return linkIsVisible; } }); add(link); AjaxLink<String> registration = new AjaxLink<String>(ID_SELF_REGISTRATION) { @Override public void onClick(AjaxRequestTarget target) { setResponsePage(PageSelfRegistration.class); } }; registration.add( new VisibleEnableBehaviour() { private static final long serialVersionUID = 1L; @Override public boolean isVisible() { OperationResult parentResult = new OperationResult(OPERATION_LOAD_REGISTRATION_POLICY); RegistrationsPolicyType registrationPolicies = null; try { Task task = createAnonymousTask(OPERATION_LOAD_REGISTRATION_POLICY); registrationPolicies = getModelInteractionService().getRegistrationPolicy(null, task, parentResult); } catch (ObjectNotFoundException | SchemaException e) { LOGGER.warn("Cannot read credentials policy: " + e.getMessage(), e); } boolean linkIsVisible = false; if (registrationPolicies != null && registrationPolicies.getSelfRegistration() != null) { linkIsVisible = true; } return linkIsVisible; } }); add(registration); } @Override protected void onConfigure() { super.onConfigure(); ServletWebRequest req = (ServletWebRequest) RequestCycle.get().getRequest(); HttpServletRequest httpReq = req.getContainerRequest(); HttpSession httpSession = httpReq.getSession(); Exception ex = (Exception) httpSession.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION); if (ex == null) { return; } String key = ex.getMessage() != null ? ex.getMessage() : "web.security.provider.unavailable"; error(getString(key)); httpSession.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION); clearBreadcrumbs(); } @Override protected void createBreadcrumb() { // don't create breadcrumb for login page } }
/** @author Kate Honchar */ public class LinksPanel extends SimplePanel<List<RichHyperlinkType>> { private static final String DOT_CLASS = LinksPanel.class.getName() + "."; private static final String ID_IMAGE = "imageId"; private static final String ID_LINK = "link"; private static final String ID_LABEL = "labelId"; private static final String ID_DESCRIPTION = "descriptionId"; private static final String ID_LINKS_ROW = "linksRow"; private static final String ID_LINKS_COLUMN = "linksColumn"; private static final String ICON_DEFAULT_CSS_CLASS = "fa fa-angle-double-right"; private static final Trace LOGGER = TraceManager.getTrace(LinksPanel.class); IModel<List<RichHyperlinkType>> model; public LinksPanel(String id) { super(id, null); } public LinksPanel( String id, IModel<List<RichHyperlinkType>> model, final List<RichHyperlinkType> linksList) { super(id, model); } @Override protected void initLayout() { final List<RichHyperlinkType> linksList = getModel().getObject(); RepeatingView rowView = new RepeatingView(ID_LINKS_ROW); int linksListSize = linksList == null ? 0 : linksList.size(); if (linksListSize > 0) { int currentColumn = 0; RepeatingView columnView = null; WebMarkupContainer row = null; boolean isRowAdded = false; for (int i = 0; i < linksListSize; i++) { final RichHyperlinkType link = linksList.get(i); if (WebMiscUtil.isAuthorized(link.getAuthorization())) { if (currentColumn == 0) { row = new WebMarkupContainer(rowView.newChildId()); isRowAdded = false; columnView = new RepeatingView(ID_LINKS_COLUMN); } WebMarkupContainer column = new WebMarkupContainer(columnView.newChildId()); Link linkItem = new Link(ID_LINK) { @Override public void onClick() {} @Override protected void onComponentTag(final ComponentTag tag) { super.onComponentTag(tag); String rootContext = ""; if (link.getTargetUrl() != null && !link.getTargetUrl().startsWith("http://") && !link.getTargetUrl().startsWith("https://") && !link.getTargetUrl().startsWith("www://") && !link.getTargetUrl().startsWith("//")) { WebApplication webApplication = WebApplication.get(); if (webApplication != null) { ServletContext servletContext = webApplication.getServletContext(); if (servletContext != null) { rootContext = servletContext.getContextPath(); } } } tag.put("href", rootContext + link.getTargetUrl()); } }; linkItem.add( new Label(ID_IMAGE) { @Override protected void onComponentTag(final ComponentTag tag) { super.onComponentTag(tag); String cssClass = ICON_DEFAULT_CSS_CLASS; if (link.getIcon() != null) { cssClass = link.getIcon().getCssClass(); } tag.put( "class", "info-box-icon " + (link.getColor() != null ? (link.getColor().startsWith("bg-") ? link.getColor() : "bg-" + link.getColor()) : "") + " " + cssClass); } }); linkItem.add( new Label( ID_LABEL, new Model<String>() { public String getObject() { return link.getLabel(); } })); Label description = new Label( ID_DESCRIPTION, new Model<String>() { public String getObject() { return link.getDescription(); } }); description.setEnabled(false); linkItem.add(description); column.add(linkItem); columnView.add(column); if (currentColumn == 1 || (linksList.indexOf(link) == linksListSize - 1)) { row.add(columnView); rowView.add(row); currentColumn = 0; isRowAdded = true; } else { currentColumn++; } } else { LOGGER.trace("Link {} not authorized, skipping", link); } } if (row != null && columnView != null && !isRowAdded) { row.add(columnView); rowView.add(row); } } add(rowView); } }
/** @author lazyman */ @Component("midpointApplication") public class MidPointApplication extends AuthenticatedWebApplication { /** Max. photo size for user/jpegPhoto */ public static final Bytes FOCUS_PHOTO_MAX_FILE_SIZE = Bytes.kilobytes(192); public static final String WEB_APP_CONFIGURATION = "midpoint.webApplication"; public static final List<LocaleDescriptor> AVAILABLE_LOCALES; private static final String LOCALIZATION_DESCRIPTOR = "/localization/locale.properties"; private static final String PROP_NAME = ".name"; private static final String PROP_FLAG = ".flag"; private static final String PROP_DEFAULT = ".default"; private static final Trace LOGGER = TraceManager.getTrace(MidPointApplication.class); static { List<LocaleDescriptor> locales = new ArrayList<>(); try { ClassLoader classLoader = MidPointApplication.class.getClassLoader(); Enumeration<URL> urls = classLoader.getResources(LOCALIZATION_DESCRIPTOR); while (urls.hasMoreElements()) { final URL url = urls.nextElement(); LOGGER.debug("Found localization descriptor {}.", new Object[] {url.toString()}); Properties properties = new Properties(); Reader reader = null; try { reader = new InputStreamReader(url.openStream(), "utf-8"); properties.load(reader); Map<String, Map<String, String>> localeMap = new HashMap<>(); Set<String> keys = (Set) properties.keySet(); for (String key : keys) { String[] array = key.split("\\."); if (array.length != 2) { continue; } String locale = array[0]; Map<String, String> map = localeMap.get(locale); if (map == null) { map = new HashMap<>(); localeMap.put(locale, map); } map.put(key, properties.getProperty(key)); } for (String key : localeMap.keySet()) { Map<String, String> localeDefinition = localeMap.get(key); if (!localeDefinition.containsKey(key + PROP_NAME) || !localeDefinition.containsKey(key + PROP_FLAG)) { continue; } LocaleDescriptor descriptor = new LocaleDescriptor( localeDefinition.get(key + PROP_NAME), localeDefinition.get(key + PROP_FLAG), localeDefinition.get(key + PROP_DEFAULT), WebComponentUtil.getLocaleFromString(key)); locales.add(descriptor); } } catch (Exception ex) { LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load localization", ex); } finally { IOUtils.closeQuietly(reader); } } Collections.sort(locales); } catch (Exception ex) { LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load locales", ex); } AVAILABLE_LOCALES = Collections.unmodifiableList(locales); } @Autowired transient ModelService model; @Autowired transient ModelInteractionService modelInteractionService; @Autowired transient TaskService taskService; @Autowired transient PrismContext prismContext; @Autowired transient ExpressionFactory expressionFactory; @Autowired transient TaskManager taskManager; @Autowired transient ModelAuditService auditService; @Autowired private transient RepositoryService repositoryService; // temporary @Autowired private transient WorkflowService workflowService; @Autowired private transient WorkflowManager workflowManager; @Autowired transient MidpointConfiguration configuration; @Autowired transient Protector protector; @Autowired transient MatchingRuleRegistry matchingRuleRegistry; @Autowired transient SecurityEnforcer securityEnforcer; private WebApplicationConfiguration webApplicationConfiguration; @Override protected void onDestroy() { GuiComponents.destroy(); super.onDestroy(); } @Override public Class<? extends PageBase> getHomePage() { if (WebComponentUtil.isAuthorized( AuthorizationConstants.AUTZ_UI_DASHBOARD_URL, AuthorizationConstants.AUTZ_UI_HOME_ALL_URL)) { return PageDashboard.class; } else { return PageSelfDashboard.class; } } @Override public void init() { super.init(); getFrameworkSettings().setSerializer(new Fast2WicketSerializer()); getJavaScriptLibrarySettings() .setJQueryReference( new PackageResourceReference( MidPointApplication.class, "../../../../../webjars/adminlte/2.3.0/plugins/jQuery/jQuery-2.1.4.min.js")); GuiComponents.init(); getComponentInstantiationListeners().add(new SpringComponentInjector(this)); ResourceSettings resourceSettings = getResourceSettings(); resourceSettings.setParentFolderPlaceholder("$-$"); resourceSettings.setHeaderItemComparator(new PriorityFirstComparator(true)); SecurePackageResourceGuard guard = (SecurePackageResourceGuard) resourceSettings.getPackageResourceGuard(); guard.addPattern("+*.woff2"); List<IStringResourceLoader> resourceLoaders = resourceSettings.getStringResourceLoaders(); resourceLoaders.add(0, new Utf8BundleStringResourceLoader("localization/Midpoint")); resourceLoaders.add( 1, new Utf8BundleStringResourceLoader( SchemaConstants.SCHEMA_LOCALIZATION_PROPERTIES_RESOURCE_BASE_PATH)); resourceSettings.setThrowExceptionOnMissingResource(false); getMarkupSettings().setStripWicketTags(true); // getMarkupSettings().setDefaultBeforeDisabledLink(""); // getMarkupSettings().setDefaultAfterDisabledLink(""); if (RuntimeConfigurationType.DEVELOPMENT.equals(getConfigurationType())) { getDebugSettings().setAjaxDebugModeEnabled(true); getDebugSettings().setDevelopmentUtilitiesEnabled(true); } // pretty url for resources (e.g. images) mountFiles(ImgResources.BASE_PATH, ImgResources.class); // exception handling an error pages ApplicationSettings appSettings = getApplicationSettings(); appSettings.setAccessDeniedPage(PageError401.class); appSettings.setInternalErrorPage(PageError.class); appSettings.setPageExpiredErrorPage(PageError.class); mount(new MountedMapper("/error", PageError.class, MidPointPageParametersEncoder.ENCODER)); mount( new MountedMapper("/error/401", PageError401.class, MidPointPageParametersEncoder.ENCODER)); mount( new MountedMapper("/error/403", PageError403.class, MidPointPageParametersEncoder.ENCODER)); mount( new MountedMapper("/error/404", PageError404.class, MidPointPageParametersEncoder.ENCODER)); mount( new MountedMapper("/error/410", PageError410.class, MidPointPageParametersEncoder.ENCODER)); getRequestCycleListeners().add(new LoggingRequestCycleListener(this)); // descriptor loader, used for customization new DescriptorLoader().loadData(this); } private void mountFiles(String path, Class<?> clazz) { try { List<Resource> list = new ArrayList<>(); String packagePath = clazz.getPackage().getName().replace('.', '/'); PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); Resource[] res = resolver.getResources("classpath:" + packagePath + "/*.png"); if (res != null) { list.addAll(Arrays.asList(res)); } res = resolver.getResources("classpath:" + packagePath + "/*.gif"); if (res != null) { list.addAll(Arrays.asList(res)); } for (Resource resource : list) { URI uri = resource.getURI(); File file = new File(uri.toString()); mountResource( path + "/" + file.getName(), new SharedResourceReference(clazz, file.getName())); } } catch (Exception ex) { LoggingUtils.logUnexpectedException(LOGGER, "Couldn't mount files", ex); } } public WebApplicationConfiguration getWebApplicationConfiguration() { if (webApplicationConfiguration == null) { Configuration config = configuration.getConfiguration(WEB_APP_CONFIGURATION); webApplicationConfiguration = new WebApplicationConfiguration(config); } return webApplicationConfiguration; } public SecurityEnforcer getSecurityEnforcer() { return securityEnforcer; } public ModelService getModel() { return model; } public TaskManager getTaskManager() { return taskManager; } public ModelAuditService getAuditService() { return auditService; } public RepositoryService getRepositoryService() { return repositoryService; } public TaskService getTaskService() { return taskService; } public PrismContext getPrismContext() { return prismContext; } public ExpressionFactory getExpressionFactory() { return expressionFactory; } public Protector getProtector() { return protector; } @Override protected Class<? extends WebPage> getSignInPageClass() { return PageLogin.class; } @Override protected Class<? extends AbstractAuthenticatedWebSession> getWebSessionClass() { return MidPointAuthWebSession.class; } public WorkflowService getWorkflowService() { return workflowService; } public WorkflowManager getWorkflowManager() { return workflowManager; } public ModelInteractionService getModelInteractionService() { return modelInteractionService; } public static boolean containsLocale(Locale locale) { if (locale == null) { return false; } for (LocaleDescriptor descriptor : AVAILABLE_LOCALES) { if (locale.equals(descriptor.getLocale())) { return true; } } return false; } public static Locale getDefaultLocale() { for (LocaleDescriptor descriptor : AVAILABLE_LOCALES) { if (descriptor.isDefault()) { return descriptor.getLocale(); } } return new Locale("en", "US"); } public MatchingRuleRegistry getMatchingRuleRegistry() { return matchingRuleRegistry; } private static class ResourceFileFilter implements FilenameFilter { @Override public boolean accept(File parent, String name) { if (name.endsWith("png") || name.endsWith("gif")) { return true; } return false; } } }
/** * Responsible for keeping the cluster consistent. (Clusterwide task management operations are in * ExecutionManager.) * * @author Pavol Mederly */ public class ClusterManager { private static final transient Trace LOGGER = TraceManager.getTrace(ClusterManager.class); private static final String CLASS_DOT = ClusterManager.class.getName() + "."; private static final String CHECK_SYSTEM_CONFIGURATION_CHANGED = CLASS_DOT + "checkSystemConfigurationChanged"; private static final String CHECK_WAITING_TASKS = CLASS_DOT + "checkWaitingTasks"; private TaskManagerQuartzImpl taskManager; private NodeRegistrar nodeRegistrar; private ClusterManagerThread clusterManagerThread; public ClusterManager(TaskManagerQuartzImpl taskManager) { this.taskManager = taskManager; this.nodeRegistrar = new NodeRegistrar(taskManager, this); } /** * Verifies cluster consistency (currently checks whether there is no other node with the same ID, * and whether clustered/non-clustered nodes are OK). * * @param result * @return */ public void checkClusterConfiguration(OperationResult result) { // LOGGER.trace("taskManager = " + taskManager); // LOGGER.trace("taskManager.getNodeRegistrar() = " + taskManager.getNodeRegistrar()); nodeRegistrar.verifyNodeObject( result); // if error, sets the error state and stops the scheduler nodeRegistrar.checkNonClusteredNodes(result); // the same } public boolean isClusterManagerThreadActive() { return clusterManagerThread != null && clusterManagerThread.isAlive(); } public void recordNodeShutdown(OperationResult result) { nodeRegistrar.recordNodeShutdown(result); } public String getNodeId() { return nodeRegistrar.getNodeId(); } public boolean isCurrentNode(PrismObject<NodeType> node) { return nodeRegistrar.isCurrentNode(node); } public boolean isCurrentNode(String node) { return nodeRegistrar.isCurrentNode(node); } public void deleteNode(String nodeOid, OperationResult result) throws SchemaException, ObjectNotFoundException { nodeRegistrar.deleteNode(nodeOid, result); } public void createNodeObject(OperationResult result) throws TaskManagerInitializationException { nodeRegistrar.createNodeObject(result); } public PrismObject<NodeType> getNodePrism() { return nodeRegistrar.getNodePrism(); } public boolean isUp(NodeType nodeType) { return nodeRegistrar.isUp(nodeType); } class ClusterManagerThread extends Thread { boolean canRun = true; @Override public void run() { LOGGER.info("ClusterManager thread starting."); long delay = taskManager.getConfiguration().getNodeRegistrationCycleTime() * 1000L; while (canRun) { OperationResult result = new OperationResult(ClusterManagerThread.class + ".run"); try { checkSystemConfigurationChanged(result); // these checks are separate in order to prevent a failure in one method blocking // execution of others try { checkClusterConfiguration(result); // if error, the scheduler will be stopped nodeRegistrar.updateNodeObject( result); // however, we want to update repo even in that case } catch (Throwable t) { LoggingUtils.logException( LOGGER, "Unexpected exception while checking cluster configuration; continuing execution.", t); } try { checkWaitingTasks(result); } catch (Throwable t) { LoggingUtils.logException( LOGGER, "Unexpected exception while checking waiting tasks; continuing execution.", t); } try { checkStalledTasks(result); } catch (Throwable t) { LoggingUtils.logException( LOGGER, "Unexpected exception while checking stalled tasks; continuing execution.", t); } } catch (Throwable t) { LoggingUtils.logException( LOGGER, "Unexpected exception in ClusterManager thread; continuing execution.", t); } LOGGER.trace("ClusterManager thread sleeping for " + delay + " msec"); try { Thread.sleep(delay); } catch (InterruptedException e) { LOGGER.trace("ClusterManager thread interrupted."); } } LOGGER.info("ClusterManager thread stopping."); } public void signalShutdown() { canRun = false; this.interrupt(); } } public void stopClusterManagerThread(long waitTime, OperationResult parentResult) { OperationResult result = parentResult.createSubresult(ClusterManager.class.getName() + ".stopClusterManagerThread"); result.addParam("waitTime", waitTime); if (clusterManagerThread != null) { clusterManagerThread.signalShutdown(); try { clusterManagerThread.join(waitTime); } catch (InterruptedException e) { LoggingUtils.logException( LOGGER, "Waiting for ClusterManagerThread shutdown was interrupted", e); } if (clusterManagerThread.isAlive()) { result.recordWarning( "ClusterManagerThread shutdown requested but after " + waitTime + " ms it is still running."); } else { result.recordSuccess(); } } else { result.recordSuccess(); } } public void startClusterManagerThread() { clusterManagerThread = new ClusterManagerThread(); clusterManagerThread.setName("ClusterManagerThread"); clusterManagerThread.start(); } private RepositoryService getRepositoryService() { return taskManager.getRepositoryService(); } public String dumpNodeInfo(NodeType node) { return node.getNodeIdentifier() + " (" + node.getHostname() + ")"; } private OperationResult createOperationResult(String methodName) { return new OperationResult(ClusterManager.class.getName() + "." + methodName); } public List<PrismObject<NodeType>> getAllNodes(OperationResult result) { try { return getRepositoryService().searchObjects(NodeType.class, null, null, result); } catch (SchemaException e) { // should not occur throw new SystemException("Cannot get the list of nodes from the repository", e); } } public PrismObject<NodeType> getNode(String nodeOid, OperationResult result) throws SchemaException, ObjectNotFoundException { return getRepositoryService().getObject(NodeType.class, nodeOid, null, result); } public PrismObject<NodeType> getNodeById(String nodeIdentifier, OperationResult result) throws ObjectNotFoundException { try { // QueryType q = QueryUtil.createNameQuery(nodeIdentifier); // TODO change // to query-by-node-id ObjectQuery q = ObjectQueryUtil.createNameQuery( NodeType.class, taskManager.getPrismContext(), nodeIdentifier); List<PrismObject<NodeType>> nodes = taskManager.getRepositoryService().searchObjects(NodeType.class, q, null, result); if (nodes.isEmpty()) { // result.recordFatalError("A node with identifier " + nodeIdentifier + " // does not exist."); throw new ObjectNotFoundException( "A node with identifier " + nodeIdentifier + " does not exist."); } else if (nodes.size() > 1) { throw new SystemException( "Multiple nodes with the same identifier '" + nodeIdentifier + "' in the repository."); } else { return nodes.get(0); } } catch (SchemaException e) { // should not occur throw new SystemException("Cannot get the list of nodes from the repository", e); } } /** * Check whether system configuration has not changed in repository (e.g. by another node in * cluster). Applies new configuration if so. * * @param parentResult */ public void checkSystemConfigurationChanged(OperationResult parentResult) { OperationResult result = parentResult.createSubresult(CHECK_SYSTEM_CONFIGURATION_CHANGED); PrismObject<SystemConfigurationType> systemConfiguration; try { PrismObject<SystemConfigurationType> config = getRepositoryService() .getObject( SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value(), null, result); String versionInRepo = config.getVersion(); String versionApplied = LoggingConfigurationManager.getCurrentlyUsedVersion(); // we do not try to determine which one is "newer" - we simply use the one from repo if (!versionInRepo.equals(versionApplied)) { LoggingConfigurationType loggingConfig = ProfilingConfigurationManager.checkSystemProfilingConfiguration(config); LoggingConfigurationManager.configure(loggingConfig, versionInRepo, result); } else { if (LOGGER.isTraceEnabled()) { LOGGER.trace( "System configuration change check: version in repo = version currently applied = {}", versionApplied); } } if (result.isUnknown()) { result.computeStatus(); } } catch (ObjectNotFoundException e) { LoggingConfigurationManager .resetCurrentlyUsedVersion(); // because the new config (if any) will have version number // probably starting at 1 - so to be sure to read it when it // comes [hope this never occurs :)] String message = "No system configuration found, skipping application of system settings"; LOGGER.error(message + ": " + e.getMessage(), e); result.recordWarning(message, e); } catch (SchemaException e) { String message = "Schema error in system configuration, skipping application of system settings"; LOGGER.error(message + ": " + e.getMessage(), e); result.recordWarning(message, e); } catch (RuntimeException e) { String message = "Runtime exception in system configuration processing, skipping application of system settings"; LOGGER.error(message + ": " + e.getMessage(), e); result.recordWarning(message, e); } } private long lastCheckedWaitingTasks = 0L; public void checkWaitingTasks(OperationResult result) throws SchemaException { if (System.currentTimeMillis() > lastCheckedWaitingTasks + taskManager.getConfiguration().getWaitingTasksCheckInterval() * 1000L) { lastCheckedWaitingTasks = System.currentTimeMillis(); taskManager.checkWaitingTasks(result); } } private long lastCheckedStalledTasks = 0L; public void checkStalledTasks(OperationResult result) throws SchemaException { if (System.currentTimeMillis() > lastCheckedStalledTasks + taskManager.getConfiguration().getStalledTasksCheckInterval() * 1000L) { lastCheckedStalledTasks = System.currentTimeMillis(); taskManager.checkStalledTasks(result); } } }