use of com.evolveum.prism.xml.ns._public.types_3.RawType in project midpoint by Evolveum.
the class ChildOfReportParamWrapperFactory method createWrapper.
@Override
public PrismReferenceWrapper<R> createWrapper(PrismContainerValueWrapper<?> parent, ItemDefinition<?> def, WrapperContext context) throws SchemaException {
ItemName name = def.getItemName();
Item<PrismValue, ItemDefinition> childItem = parent.getNewValue().findItem(name);
if ((skipCreateWrapper(def, ItemStatus.NOT_CHANGED, context, childItem == null || CollectionUtils.isEmpty(childItem.getValues()))) || !(childItem.getRealValue() instanceof RawType)) {
LOGGER.trace("Skipping creating wrapper for non-existent item. It is not supported for {}", def);
if (parent != null && parent.getNewValue() != null) {
parent.getNewValue().remove(childItem);
}
return null;
}
if (childItem == null) {
childItem = parent.getNewValue().findOrCreateItem(name);
}
PrismReference newItem = (PrismReference) def.instantiate();
ObjectReferenceType parsedRealValue = ((RawType) childItem.getRealValue()).getParsedRealValue(ObjectReferenceType.class);
newItem.add(parsedRealValue.asReferenceValue());
PrismReferenceWrapper<R> itemWrapper = createWrapperInternal(parent, newItem, ItemStatus.NOT_CHANGED, context);
itemWrapper.setMetadata(context.isMetadata());
itemWrapper.setProcessProvenanceMetadata(context.isProcessMetadataFor(itemWrapper.getPath()));
registerWrapperPanel(itemWrapper);
List<PrismReferenceValueWrapperImpl<R>> valueWrappers = createValuesWrapper(itemWrapper, newItem, context);
itemWrapper.getValues().addAll(valueWrappers);
itemWrapper.setShowEmpty(context.isShowEmpty(), false);
setupWrapper(itemWrapper);
return itemWrapper;
}
use of com.evolveum.prism.xml.ns._public.types_3.RawType in project midpoint by Evolveum.
the class TestParseDiffPatch method assertModificationPolyStringValue.
private void assertModificationPolyStringValue(RawType value, PolyStringType... expectedValues) throws SchemaException {
XNode xnode = value.serializeToXNode();
assertFalse(xnode.isEmpty());
PrismContext pc = value.getPrismContext();
RootXNode rootNode = pc.xnodeFactory().root(new ItemName("dummy"), xnode);
PolyStringType valueAsPoly = pc.parserFor(rootNode).parseRealValue(PolyStringType.class);
boolean found = false;
for (PolyStringType expectedValue : expectedValues) {
if (expectedValue.getOrig().equals(valueAsPoly.getOrig()) && expectedValue.getNorm().equals(valueAsPoly.getNorm())) {
found = true;
break;
}
}
assertTrue(found);
}
use of com.evolveum.prism.xml.ns._public.types_3.RawType in project midpoint by Evolveum.
the class AbstractDirectManualResourceTest method test250RecomputeWillAfter5min.
/**
* lets ff 5min just for fun. Refresh, make sure everything should be the same (grace not expired yet)
*/
@Test
public void test250RecomputeWillAfter5min() throws Exception {
// GIVEN
Task task = getTestTask();
OperationResult result = task.getResult();
clockForward("PT5M");
PrismObject<ShadowType> shadowBefore = modelService.getObject(ShadowType.class, accountWillOid, null, task, result);
display("Shadow before", shadowBefore);
// WHEN
when();
recomputeUser(userWillOid, task, result);
// THEN
then();
assertSuccess(result);
PrismObject<ShadowType> shadowRepo = repositoryService.getObject(ShadowType.class, accountWillOid, null, result);
display("Repo shadow", shadowRepo);
assertPendingOperationDeltas(shadowRepo, 3);
PendingOperationType pendingOperation = findPendingOperation(shadowRepo, OperationResultStatusType.SUCCESS, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS);
assertPendingOperation(shadowRepo, pendingOperation, accountWillReqestTimestampStart, accountWillReqestTimestampEnd, PendingOperationExecutionStatusType.COMPLETED, OperationResultStatusType.SUCCESS, accountWillCompletionTimestampStart, accountWillCompletionTimestampEnd);
pendingOperation = findPendingOperation(shadowRepo, OperationResultStatusType.IN_PROGRESS, SchemaConstants.PATH_PASSWORD_VALUE);
assertPendingOperation(shadowRepo, pendingOperation, accountWillSecondReqestTimestampStart, accountWillSecondReqestTimestampEnd);
assertShadowActivationAdministrativeStatusFromCache(shadowRepo, ActivationStatusType.DISABLED);
assertAttribute(shadowRepo, ATTR_USERNAME_QNAME, new RawType(itemFactory().createPropertyValue(USER_WILL_NAME), ATTR_USERNAME_QNAME, prismContext));
assertAttributeFromCache(shadowRepo, ATTR_FULLNAME_QNAME, RawType.fromPropertyRealValue(USER_WILL_FULL_NAME_PIRATE, ATTR_FULLNAME_QNAME, prismContext));
PrismObject<ShadowType> shadowModel = modelService.getObject(ShadowType.class, accountWillOid, null, task, result);
display("Model shadow", shadowModel);
ShadowType shadowTypeProvisioning = shadowModel.asObjectable();
assertShadowName(shadowModel, USER_WILL_NAME);
assertEquals("Wrong kind (provisioning)", ShadowKindType.ACCOUNT, shadowTypeProvisioning.getKind());
if (supportsBackingStore()) {
assertShadowActivationAdministrativeStatus(shadowModel, ActivationStatusType.ENABLED);
} else {
assertShadowActivationAdministrativeStatus(shadowModel, ActivationStatusType.DISABLED);
}
assertAttribute(shadowModel, ATTR_USERNAME_QNAME, USER_WILL_NAME);
assertAttribute(shadowModel, ATTR_FULLNAME_QNAME, USER_WILL_FULL_NAME_PIRATE);
assertAttributeFromBackingStore(shadowModel, ATTR_DESCRIPTION_QNAME, ACCOUNT_WILL_DESCRIPTION_MANUAL);
assertShadowPassword(shadowModel);
assertPendingOperationDeltas(shadowModel, 3);
pendingOperation = findPendingOperation(shadowModel, OperationResultStatusType.SUCCESS, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS);
assertPendingOperation(shadowModel, pendingOperation, accountWillReqestTimestampStart, accountWillReqestTimestampEnd, PendingOperationExecutionStatusType.COMPLETED, OperationResultStatusType.SUCCESS, accountWillCompletionTimestampStart, accountWillCompletionTimestampEnd);
PrismObject<ShadowType> shadowProvisioningFuture = modelService.getObject(ShadowType.class, accountWillOid, SelectorOptions.createCollection(GetOperationOptions.createPointInTimeType(PointInTimeType.FUTURE)), task, result);
display("Model shadow (future)", shadowProvisioningFuture);
assertShadowName(shadowProvisioningFuture, USER_WILL_NAME);
assertEquals("Wrong kind (provisioning)", ShadowKindType.ACCOUNT, shadowProvisioningFuture.asObjectable().getKind());
assertShadowActivationAdministrativeStatus(shadowProvisioningFuture, ActivationStatusType.ENABLED);
assertAttribute(shadowProvisioningFuture, ATTR_USERNAME_QNAME, USER_WILL_NAME);
assertAttribute(shadowProvisioningFuture, ATTR_FULLNAME_QNAME, USER_WILL_FULL_NAME_PIRATE);
assertAttributeFromBackingStore(shadowProvisioningFuture, ATTR_DESCRIPTION_QNAME, ACCOUNT_WILL_DESCRIPTION_MANUAL);
// TODO
// assertShadowPassword(shadowProvisioningFuture);
assertCaseState(willLastCaseOid, SchemaConstants.CASE_STATE_CLOSED);
assertCaseState(willSecondLastCaseOid, SchemaConstants.CASE_STATE_OPEN);
assertSteadyResources();
}
use of com.evolveum.prism.xml.ns._public.types_3.RawType in project midpoint by Evolveum.
the class TestRecomputeTask method test100RecomputeAll.
@Test
public void test100RecomputeAll() throws Exception {
// GIVEN
Task task = getTestTask();
OperationResult result = getTestOperationResult();
// Preconditions
assertUsers(6);
assertNoDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_GUYBRUSH_DUMMY_USERNAME);
assertNoDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME);
// Do some ordinary operations
assignRole(USER_GUYBRUSH_OID, ROLE_PIRATE_OID, task, result);
assignRole(USER_JACK_OID, ROLE_JUDGE_OID, task, result);
addObject(USER_HERMAN_FILE);
assignRole(USER_HERMAN_OID, ROLE_JUDGE_OID, task, result);
result.computeStatus();
TestUtil.assertSuccess(result);
// Now do something evil
// change definition of role "pirate". midPoint will not recompute automatically
// the recompute task should do it
// One simple change
modifyRoleAddConstruction(ROLE_JUDGE_OID, 1111L, RESOURCE_DUMMY_RED_OID);
// More complicated change
PrismObject<RoleType> rolePirate = modelService.getObject(RoleType.class, ROLE_PIRATE_OID, null, task, result);
ItemPath attrItemPath = ItemPath.create(RoleType.F_INDUCEMENT, 1111L, AssignmentType.F_CONSTRUCTION, 60004L, ConstructionType.F_ATTRIBUTE);
PrismContainer<ResourceAttributeDefinitionType> attributeCont = rolePirate.findContainer(attrItemPath);
assertNotNull("No attribute property in " + rolePirate, attributeCont);
PrismContainerValue<ResourceAttributeDefinitionType> oldAttrContainer = null;
for (PrismContainerValue<ResourceAttributeDefinitionType> cval : attributeCont.getValues()) {
ResourceAttributeDefinitionType attrType = cval.getValue();
if (ItemPathTypeUtil.asSingleNameOrFail(attrType.getRef()).getLocalPart().equals(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_WEAPON_NAME)) {
oldAttrContainer = cval;
}
}
assertNotNull("Definition for weapon attribute not found in " + rolePirate, oldAttrContainer);
PrismContainerValue<ResourceAttributeDefinitionType> newAttrContainer = oldAttrContainer.clone();
XNode daggerXNode = prismContext.xnodeFactory().primitive("dagger");
daggerXNode.freeze();
RawType daggerValueEvaluator = new RawType(daggerXNode, prismContext);
JAXBElement<?> daggerExpressionEvalJaxbElement = new JAXBElement<>(SchemaConstants.C_VALUE, Object.class, daggerValueEvaluator);
newAttrContainer.getValue().getOutbound().getExpression().getExpressionEvaluator().add(daggerExpressionEvalJaxbElement);
newAttrContainer.getValue().getOutbound().setStrength(MappingStrengthType.STRONG);
ObjectDelta<RoleType> rolePirateDelta = prismContext.deltaFactory().object().createModificationDeleteContainer(RoleType.class, ROLE_PIRATE_OID, attrItemPath, oldAttrContainer.getValue().clone());
ResourceAttributeDefinitionType newAttrCVal = newAttrContainer.getValue();
newAttrCVal.asPrismContainerValue().setId(null);
rolePirateDelta.addModificationAddContainer(attrItemPath, newAttrCVal);
displayDumpable("Role pirate delta", rolePirateDelta);
modelService.executeChanges(MiscSchemaUtil.createCollection(rolePirateDelta), null, task, result);
displayRoles(task, result);
assertDummyAccount(null, ACCOUNT_GUYBRUSH_DUMMY_USERNAME, "Guybrush Threepwood", true);
assertNoDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_GUYBRUSH_DUMMY_USERNAME);
assertUser(USER_JACK_OID, "user jack before").display().assignments().single().assertRole(ROLE_JUDGE_OID).end().end().roleMembershipRefs().single().assertOid(ROLE_JUDGE_OID);
assertDummyAccount(null, ACCOUNT_JACK_DUMMY_USERNAME, "Jack Sparrow", true);
assertNoDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME);
result.computeStatus();
TestUtil.assertSuccess(result);
// WHEN
when();
addTask(TASK_USER_RECOMPUTE_FILE);
dummyAuditService.clear();
waitForTaskStart(TASK_USER_RECOMPUTE_OID, false);
// WHEN
when();
waitForTaskFinish(TASK_USER_RECOMPUTE_OID, false, 40000);
// THEN
then();
List<PrismObject<UserType>> users = modelService.searchObjects(UserType.class, null, null, task, result);
display("Users after recompute", users);
assertDummyAccount(null, ACCOUNT_GUYBRUSH_DUMMY_USERNAME, "Guybrush Threepwood", true);
assertDummyAccountAttribute(null, ACCOUNT_GUYBRUSH_DUMMY_USERNAME, DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_WEAPON_NAME, "cutlass", "dagger");
assertNoDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_GUYBRUSH_DUMMY_USERNAME);
assertUser(USER_JACK_OID, "user jack after").display().assertNoArchetypeRef();
assertNoDummyAccount(null, ACCOUNT_JACK_DUMMY_USERNAME);
assertDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, "Jack Sparrow", true);
assertUsers(7);
// Check audit
displayDumpable("Audit", dummyAuditService);
List<AuditEventRecord> auditRecords = dummyAuditService.getRecords();
int i = 0;
int modifications = 0;
for (; i < (auditRecords.size() - 1); i += 2) {
AuditEventRecord requestRecord = auditRecords.get(i);
assertNotNull("No request audit record (" + i + ")", requestRecord);
assertEquals("Got this instead of request audit record (" + i + "): " + requestRecord, AuditEventStage.REQUEST, requestRecord.getEventStage());
assertTrue("Unexpected delta in request audit record " + requestRecord, requestRecord.getDeltas().isEmpty());
AuditEventRecord executionRecord = auditRecords.get(i + 1);
assertNotNull("No execution audit record (" + i + ")", executionRecord);
assertEquals("Got this instead of execution audit record (" + i + "): " + executionRecord, AuditEventStage.EXECUTION, executionRecord.getEventStage());
assertThat(executionRecord.getDeltas()).withFailMessage("Empty deltas in execution audit record " + executionRecord).isNotEmpty();
modifications++;
// check next records
while (i < (auditRecords.size() - 2)) {
AuditEventRecord nextRecord = auditRecords.get(i + 2);
if (nextRecord.getEventStage() == AuditEventStage.EXECUTION) {
// more than one execution record is OK
i++;
} else {
break;
}
}
}
assertEquals("Unexpected number of audit modifications", 7, modifications);
deleteObject(TaskType.class, TASK_USER_RECOMPUTE_OID, task, result);
}
use of com.evolveum.prism.xml.ns._public.types_3.RawType in project midpoint by Evolveum.
the class MailMessageTransport method send.
@Override
public void send(Message mailMessage, String transportName, Event event, Task task, OperationResult parentResult) {
OperationResult result = parentResult.createSubresult(DOT_CLASS + "send");
result.addArbitraryObjectCollectionAsParam("mailMessage recipient(s)", mailMessage.getTo());
result.addParam("mailMessage subject", mailMessage.getSubject());
String logToFile = configuration.getLogToFile();
if (logToFile != null) {
TransportUtil.logToFile(logToFile, formatToFileOld(mailMessage), LOGGER);
}
String redirectToFile = configuration.getRedirectToFile();
int optionsForFilteringRecipient = TransportUtil.optionsForFilteringRecipient(configuration);
List<String> allowedRecipientTo = new ArrayList<>();
List<String> forbiddenRecipientTo = new ArrayList<>();
List<String> allowedRecipientCc = new ArrayList<>();
List<String> forbiddenRecipientCc = new ArrayList<>();
List<String> allowedRecipientBcc = new ArrayList<>();
List<String> forbiddenRecipientBcc = new ArrayList<>();
if (optionsForFilteringRecipient != 0) {
TransportUtil.validateRecipient(allowedRecipientTo, forbiddenRecipientTo, mailMessage.getTo(), configuration, task, result, transportSupport.expressionFactory(), MiscSchemaUtil.getExpressionProfile(), LOGGER);
TransportUtil.validateRecipient(allowedRecipientCc, forbiddenRecipientCc, mailMessage.getCc(), configuration, task, result, transportSupport.expressionFactory(), MiscSchemaUtil.getExpressionProfile(), LOGGER);
TransportUtil.validateRecipient(allowedRecipientBcc, forbiddenRecipientBcc, mailMessage.getBcc(), configuration, task, result, transportSupport.expressionFactory(), MiscSchemaUtil.getExpressionProfile(), LOGGER);
if (redirectToFile != null) {
if (!forbiddenRecipientTo.isEmpty() || !forbiddenRecipientCc.isEmpty() || !forbiddenRecipientBcc.isEmpty()) {
mailMessage.setTo(forbiddenRecipientTo);
mailMessage.setCc(forbiddenRecipientCc);
mailMessage.setBcc(forbiddenRecipientBcc);
TransportUtil.appendToFile(redirectToFile, formatToFileOld(mailMessage), LOGGER, result);
}
mailMessage.setTo(allowedRecipientTo);
mailMessage.setCc(allowedRecipientCc);
mailMessage.setBcc(allowedRecipientBcc);
}
} else if (redirectToFile != null) {
TransportUtil.appendToFile(redirectToFile, formatToFileOld(mailMessage), LOGGER, result);
return;
}
if (optionsForFilteringRecipient != 0 && mailMessage.getTo().isEmpty()) {
String msg = "No recipient found after recipient validation.";
LOGGER.debug(msg);
result.recordSuccess();
return;
}
if (configuration.getServer().isEmpty()) {
String msg = "Mail server(s) are not defined, mail notification to " + mailMessage.getTo() + " will not be sent.";
LOGGER.warn(msg);
result.recordWarning(msg);
return;
}
long start = System.currentTimeMillis();
String defaultFrom = configuration.getDefaultFrom() != null ? configuration.getDefaultFrom() : "nobody@nowhere.org";
for (MailServerConfigurationType mailServerConfigurationType : configuration.getServer()) {
OperationResult resultForServer = result.createSubresult(DOT_CLASS + "send.forServer");
final String host = mailServerConfigurationType.getHost();
resultForServer.addContext("server", host);
resultForServer.addContext("port", mailServerConfigurationType.getPort());
Properties properties = System.getProperties();
properties.setProperty("mail.smtp.host", host);
if (mailServerConfigurationType.getPort() != null) {
properties.setProperty("mail.smtp.port", String.valueOf(mailServerConfigurationType.getPort()));
}
MailTransportSecurityType mailTransportSecurityType = mailServerConfigurationType.getTransportSecurity();
boolean sslEnabled = false, starttlsEnable = false, starttlsRequired = false;
if (mailTransportSecurityType != null) {
switch(mailTransportSecurityType) {
case STARTTLS_ENABLED:
starttlsEnable = true;
break;
case STARTTLS_REQUIRED:
starttlsEnable = true;
starttlsRequired = true;
break;
case SSL:
sslEnabled = true;
break;
}
}
properties.put("mail.smtp.ssl.enable", "" + sslEnabled);
properties.put("mail.smtp.starttls.enable", "" + starttlsEnable);
properties.put("mail.smtp.starttls.required", "" + starttlsRequired);
if (Boolean.TRUE.equals(configuration.isDebug())) {
properties.put("mail.debug", "true");
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Using mail properties: ");
for (Object key : properties.keySet()) {
if (key instanceof String && ((String) key).startsWith("mail.")) {
LOGGER.debug(" - {} = {}", key, properties.get(key));
}
}
}
task.recordStateMessage("Sending notification mail via " + host);
Session session = Session.getInstance(properties);
try {
MimeMessage mimeMessage = new MimeMessage(session);
mimeMessage.setSentDate(new Date());
String from = mailMessage.getFrom() != null ? mailMessage.getFrom() : defaultFrom;
mimeMessage.setFrom(new InternetAddress(from));
for (String recipient : mailMessage.getTo()) {
mimeMessage.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(recipient));
}
for (String recipientCc : mailMessage.getCc()) {
mimeMessage.addRecipient(javax.mail.Message.RecipientType.CC, new InternetAddress(recipientCc));
}
for (String recipientBcc : mailMessage.getBcc()) {
mimeMessage.addRecipient(javax.mail.Message.RecipientType.BCC, new InternetAddress(recipientBcc));
}
mimeMessage.setSubject(mailMessage.getSubject(), StandardCharsets.UTF_8.name());
String contentType = mailMessage.getContentType();
if (StringUtils.isEmpty(contentType)) {
contentType = "text/plain; charset=UTF-8";
}
BodyPart messageBody = new MimeBodyPart();
messageBody.setContent(mailMessage.getBody(), contentType);
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBody);
for (NotificationMessageAttachmentType attachment : mailMessage.getAttachments()) {
if (attachment.getContent() != null || attachment.getContentFromFile() != null) {
String fileName;
BodyPart attachmentBody = new MimeBodyPart();
if (attachment.getContent() != null) {
try {
Object content = RawType.getValue(attachment.getContent());
if (content == null) {
LOGGER.warn("RawType " + attachment.getContent() + " isn't possible to parse.");
return;
}
attachmentBody.setContent(content, attachment.getContentType());
} catch (SchemaException e) {
LOGGER.warn("RawType " + attachment.getContent() + " isn't possible to parse.");
return;
}
if (StringUtils.isBlank(attachment.getFileName())) {
fileName = "attachment";
} else {
fileName = attachment.getFileName();
}
} else {
if (!Files.isReadable(Paths.get(attachment.getContentFromFile()))) {
LOGGER.warn("File " + attachment.getContentFromFile() + " non exist or isn't readable.");
return;
}
DataSource source = new FileDataSource(attachment.getContentFromFile()) {
@Override
public String getContentType() {
return attachment.getContentType();
}
};
attachmentBody.setDataHandler(new DataHandler(source));
if (StringUtils.isBlank(attachment.getFileName())) {
fileName = source.getName();
} else {
fileName = attachment.getFileName();
}
}
if (!fileName.contains(".")) {
fileName += MimeTypeUtil.getDefaultExt(attachment.getContentType());
}
attachmentBody.setFileName(fileName);
if (!StringUtils.isBlank(attachment.getContentId())) {
attachmentBody.setHeader("Content-ID", attachment.getContentId());
}
multipart.addBodyPart(attachmentBody);
} else {
LOGGER.warn("NotificationMessageAttachmentType doesn't contain content.");
}
}
mimeMessage.setContent(multipart);
try (javax.mail.Transport t = session.getTransport("smtp")) {
if (StringUtils.isNotEmpty(mailServerConfigurationType.getUsername())) {
ProtectedStringType passwordProtected = mailServerConfigurationType.getPassword();
String password = null;
if (passwordProtected != null) {
try {
password = transportSupport.protector().decryptString(passwordProtected);
} catch (EncryptionException e) {
String msg = "Couldn't send mail message to " + mailMessage.getTo() + " via " + host + ", because the plaintext password value couldn't be obtained. Trying another mail server, if there is any.";
LoggingUtils.logException(LOGGER, msg, e);
resultForServer.recordFatalError(msg, e);
continue;
}
}
t.connect(mailServerConfigurationType.getUsername(), password);
} else {
t.connect();
}
t.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
LOGGER.debug("Message sent successfully to " + mailMessage.getTo() + " via server " + host + ".");
resultForServer.recordSuccess();
result.recordSuccess();
long duration = System.currentTimeMillis() - start;
task.recordStateMessage("Notification mail sent successfully via " + host + ", in " + duration + " ms overall.");
task.recordNotificationOperation(name, true, duration);
}
return;
} catch (MessagingException e) {
String msg = "Couldn't send mail message to " + mailMessage.getTo() + " via " + host + ", trying another mail server, if there is any";
LoggingUtils.logException(LOGGER, msg, e);
resultForServer.recordFatalError(msg, e);
task.recordStateMessage("Error sending notification mail via " + host);
}
}
LOGGER.warn("No more mail servers to try, mail notification to " + mailMessage.getTo() + " will not be sent.");
result.recordWarning("Mail notification to " + mailMessage.getTo() + " could not be sent.");
task.recordNotificationOperation(name, false, System.currentTimeMillis() - start);
}
Aggregations