diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/result/OperationResult.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/result/OperationResult.java index 72a9b592f31..8cc2bcf7aee 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/result/OperationResult.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/result/OperationResult.java @@ -1043,6 +1043,10 @@ public void recordNotApplicableIfUnknown() { } } + public void recordNotApplicable() { + recordStatus(OperationResultStatus.NOT_APPLICABLE, (String) null); + } + public boolean isMinor() { return importance == MINOR; } diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestNotifications.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestNotifications.java index 6f2ceb1253f..d47c88b6b54 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestNotifications.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestNotifications.java @@ -126,6 +126,8 @@ public void test100ModifyUserAddAccount() throws Exception { XMLGregorianCalendar startTime = clock.currentTimeXMLGregorianCalendar(); + setGlobalTracingOverride(createModelLoggingTracingProfile()); + // WHEN when(); modifyUserAddAccount(USER_JACK_OID, ACCOUNT_JACK_DUMMY_FILE, task, result); @@ -206,6 +208,9 @@ public void test100ModifyUserAddAccount() throws Exception { @Test public void test119ModifyUserDeleteAccount() throws Exception { + + unsetGlobalTracingOverride(); + // GIVEN Task task = createPlainTask(); OperationResult result = task.getResult(); diff --git a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/EventHandler.java b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/EventHandler.java index ef417bf969f..c2ef6d87a66 100644 --- a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/EventHandler.java +++ b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/EventHandler.java @@ -13,13 +13,20 @@ import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.xml.ns._public.common.common_3.EventHandlerType; -/** - * @author mederly - */ -@FunctionalInterface -public interface EventHandler { +public interface EventHandler { + + /** + * @return true if we should continue with processing, false otherwise + */ + boolean processEvent(E event, C eventHandlerType, Task task, OperationResult result) throws SchemaException; + + /** + * @return Type of events this handler is capable of handling. + */ + Class getEventType(); - // true if we should continue with processing, false otherwise - boolean processEvent(Event event, EventHandlerType eventHandlerType, NotificationManager notificationManager, - Task task, OperationResult result) throws SchemaException; + /** + * @return Type of configuration objects for this event handler. The handler is selected based on exact match of this type. + */ + Class getEventHandlerConfigurationType(); } diff --git a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/NotificationManager.java b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/NotificationManager.java index f055576f003..9af5bfdbf92 100644 --- a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/NotificationManager.java +++ b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/NotificationManager.java @@ -13,21 +13,20 @@ import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.xml.ns._public.common.common_3.EventHandlerType; +import org.jetbrains.annotations.NotNull; + /** - * @author mederly + * Handles notification events. */ - public interface NotificationManager { void registerTransport(String name, Transport transport); - Transport getTransport(String name); - // event may be null - void processEvent(Event event, Task task, OperationResult result); + void processEvent(@NotNull Event event, Task task, OperationResult result); - - boolean processEvent(Event event, EventHandlerType eventHandlerType, Task task, OperationResult result); + boolean processEvent(@NotNull Event event, EventHandlerType eventHandlerBean, Task task, OperationResult result); boolean isDisabled(); + void setDisabled(boolean disabled); } diff --git a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/CertReviewEvent.java b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/CertReviewEvent.java index 0b935441885..0014cacafe1 100644 --- a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/CertReviewEvent.java +++ b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/CertReviewEvent.java @@ -51,11 +51,6 @@ public boolean isCategoryType(EventCategoryType eventCategoryType) { EventCategoryType.CERT_CASE_EVENT.equals(eventCategoryType); } - @Deprecated // obsolete name - public Collection getCasesAwaitingResponseFromRequestee() { - return getCasesAwaitingResponseFromActualReviewer(); - } - public Collection getCasesAwaitingResponseFromActualReviewer() { List rv = new ArrayList<>(); for (AccessCertificationCaseType aCase : cases) { diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/AccountOperationListener.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/AccountOperationListener.java index ec5ddd1e5d0..4dc3b52bac1 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/AccountOperationListener.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/AccountOperationListener.java @@ -26,6 +26,7 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @@ -148,6 +149,7 @@ private void executeNotifyAny(OperationStatus status, ResourceOperationDescripti notificationManager.processEvent(request, task, result); } + @NotNull private ResourceObjectEvent createRequest(OperationStatus status, ResourceOperationDescription operationDescription, Task task, diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/EventHandlerRegistry.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/EventHandlerRegistry.java new file mode 100644 index 00000000000..0c2b0f0d555 --- /dev/null +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/EventHandlerRegistry.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.notifications.impl; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.notifications.api.EventHandler; +import com.evolveum.midpoint.notifications.api.events.Event; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.EventHandlerType; + +/** + * + */ +@Component +public class EventHandlerRegistry { + + private static final Trace LOGGER = TraceManager.getTrace(EventHandlerRegistry.class); + + private Map, EventHandler> handlers = new ConcurrentHashMap<>(); + + public void registerEventHandler(Class configType, EventHandler handler) { + LOGGER.trace("Registering event handler {} for config type {}", handler, configType); + handlers.put(configType, handler); + } + + public boolean forwardToHandler(Event event, EventHandlerType configuration, Task task, OperationResult result) throws SchemaException { + EventHandler handler = handlers.get(configuration.getClass()); + if (handler == null) { + throw new IllegalStateException("Unknown handler for " + configuration); + } else if (!handler.getEventType().isAssignableFrom(event.getClass())) { + LOGGER.trace("Not forwarding event {} to handler {} because the handler does not support events of that type", + event, handler); + return true; + } else { + //noinspection unchecked,rawtypes + return ((EventHandler) handler).processEvent(event, configuration, task, result); + } + } +} diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/NotificationHook.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/NotificationHook.java index 16cea5d1fe0..d63d0996bcf 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/NotificationHook.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/NotificationHook.java @@ -51,6 +51,8 @@ public class NotificationHook implements ChangeHook { private static final String HOOK_URI = SchemaConstants.NS_MODEL + "/notification-hook-3"; + private static final String OP_INVOKE = NotificationHook.class.getName() + ".invoke"; + @Autowired private LightweightIdentifierGenerator lightweightIdentifierGenerator; @Autowired private HookRegistry hookRegistry; @Autowired private NotificationManager notificationManager; @@ -59,36 +61,37 @@ public class NotificationHook implements ChangeHook { @PostConstruct public void init() { hookRegistry.registerChangeHook(HOOK_URI, this); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Notifier change hook registered."); - } + LOGGER.trace("Notifier change hook registered."); } @Override - public HookOperationMode invoke(@NotNull ModelContext context, @NotNull Task task, @NotNull OperationResult result) { - - // todo in the future we should perhaps act in POSTEXECUTION state, but currently the clockwork skips this state - if (context.getState() != ModelState.FINAL) { - return HookOperationMode.FOREGROUND; - } - if (notificationManager.isDisabled()) { - LOGGER.trace("Notifications are temporarily disabled, exiting the hook."); - return HookOperationMode.FOREGROUND; - } - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Notification change hook called with model context: " + context.debugDump()); - } - if (context.getFocusContext() == null) { - if (LOGGER.isTraceEnabled()) { + public HookOperationMode invoke(@NotNull ModelContext context, @NotNull Task task, + @NotNull OperationResult parentResult) { + OperationResult result = parentResult.createSubresult(OP_INVOKE); + try { + if (context.getState() != ModelState.FINAL) { + return HookOperationMode.FOREGROUND; + } + if (notificationManager.isDisabled()) { + LOGGER.trace("Notifications are temporarily disabled, exiting the hook."); + return HookOperationMode.FOREGROUND; + } + LOGGER.trace("Notification change hook called with model context:\n{}", context.debugDumpLazily()); + if (context.getFocusContext() == null) { LOGGER.trace("Focus context is null, exiting the hook."); + return HookOperationMode.FOREGROUND; } - return HookOperationMode.FOREGROUND; - } - emitModelEvent(context, task, result); - emitPolicyRulesEvents(context, task, result); + emitModelEvent(context, task, result); + emitPolicyRulesEvents(context, task, result); - return HookOperationMode.FOREGROUND; + return HookOperationMode.FOREGROUND; + } catch (Throwable t) { + result.recordFatalError(t); + throw t; + } finally { + result.computeStatusIfUnknown(); + } } private void emitPolicyRulesEvents(ModelContext context, Task task, OperationResult result) { diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/NotificationManagerImpl.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/NotificationManagerImpl.java index 38861419aa3..ac702e307ee 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/NotificationManagerImpl.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/NotificationManagerImpl.java @@ -7,7 +7,6 @@ package com.evolveum.midpoint.notifications.impl; -import com.evolveum.midpoint.notifications.api.EventHandler; import com.evolveum.midpoint.notifications.api.NotificationFunctions; import com.evolveum.midpoint.notifications.api.NotificationManager; import com.evolveum.midpoint.notifications.api.events.BaseEvent; @@ -18,7 +17,6 @@ import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.task.api.TaskManager; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; @@ -26,13 +24,12 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.EventHandlerType; import com.evolveum.midpoint.xml.ns._public.common.common_3.NotificationConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; -import org.jetbrains.annotations.Nullable; + +import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; -import java.util.HashMap; - /** * @author mederly */ @@ -41,7 +38,7 @@ public class NotificationManagerImpl implements NotificationManager { private static final Trace LOGGER = TraceManager.getTrace(NotificationManager.class); - private static final String OPERATION_PROCESS_EVENT = NotificationManager.class + ".processEvent"; + private static final String OP_PROCESS_EVENT = NotificationManager.class + ".processEvent"; @Autowired @Qualifier("cacheRepositoryService") @@ -49,124 +46,67 @@ public class NotificationManagerImpl implements NotificationManager { @Autowired private PrismContext prismContext; @Autowired private NotificationFunctions notificationFunctions; - @Autowired private TaskManager taskManager; - - private boolean disabled = false; // for testing purposes (in order for model-intest to run more quickly) - - private HashMap,EventHandler> handlers = new HashMap<>(); - private HashMap transports = new HashMap<>(); + @Autowired private TransportRegistry transportRegistry; + @Autowired private EventHandlerRegistry eventHandlerRegistry; - public void registerEventHandler(Class clazz, EventHandler handler) { - LOGGER.trace("Registering event handler " + handler + " for " + clazz); - handlers.put(clazz, handler); - } - - public EventHandler getEventHandler(EventHandlerType eventHandlerType) { - EventHandler handler = handlers.get(eventHandlerType.getClass()); - if (handler == null) { - throw new IllegalStateException("Unknown handler for " + eventHandlerType); - } else { - return handler; - } - } + private boolean disabled = false; // for testing purposes (in order for model-intest to run more quickly) @Override public void registerTransport(String name, Transport transport) { - LOGGER.trace("Registering notification transport {} under name {}", transport, name); - transports.put(name, transport); + transportRegistry.registerTransport(name, transport); } - // accepts name:subname (e.g. dummy:accounts) - a primitive form of passing parameters (will be enhanced/replaced in the future) @Override - public Transport getTransport(String name) { - String key = name.split(":")[0]; - Transport transport = transports.get(key); - if (transport == null) { - throw new IllegalStateException("Unknown transport named " + key); - } else { - return transport; + public void processEvent(@NotNull Event event, Task task, OperationResult parentResult) { + OperationResult result = parentResult.subresult(OP_PROCESS_EVENT) + .addArbitraryObjectAsParam("event", event) + .build(); + try { + if (event instanceof BaseEvent) { + ((BaseEvent) event).setNotificationFunctions(notificationFunctions); + ((BaseEvent) event).setPrismContext(prismContext); + } + + LOGGER.trace("NotificationManager processing event:\n{}", event.debugDumpLazily(1)); + + if (event.getAdHocHandler() != null) { + processEvent(event, event.getAdHocHandler(), task, result); + } + + SystemConfigurationType systemConfigurationType = getSystemConfiguration(task, result); + if (systemConfigurationType == null) { + LOGGER.trace("No system configuration in repository, are we doing initial import?"); + } else if (systemConfigurationType.getNotificationConfiguration() == null) { + LOGGER.trace("No notification configuration in repository, finished event processing."); + } else { + NotificationConfigurationType notificationConfiguration = systemConfigurationType.getNotificationConfiguration(); + for (EventHandlerType eventHandlerBean : notificationConfiguration.getHandler()) { + processEvent(event, eventHandlerBean, task, result); + } + LOGGER.trace("NotificationManager successfully processed event {} ({} top level handler(s))", event, + notificationConfiguration.getHandler().size()); + } + } catch (Throwable t) { + result.recordFatalError(t); + throw t; + } finally { + result.computeStatusIfUnknown(); } } - public void processEvent(@Nullable Event event, Task task, OperationResult result) { - if (event == null) { - return; - } - - if (event instanceof BaseEvent) { - ((BaseEvent) event).setNotificationFunctions(notificationFunctions); - ((BaseEvent) event).setPrismContext(prismContext); - } - - LOGGER.trace("NotificationManager processing event:\n{}", event.debugDumpLazily(1)); - - if (event.getAdHocHandler() != null) { - processEvent(event, event.getAdHocHandler(), task, result); - } - + private SystemConfigurationType getSystemConfiguration(Task task, OperationResult result) { boolean errorIfNotFound = !SchemaConstants.CHANNEL_GUI_INIT_URI.equals(task.getChannel()); - SystemConfigurationType systemConfigurationType = NotificationFunctionsImpl + return NotificationFunctionsImpl .getSystemConfiguration(cacheRepositoryService, errorIfNotFound, result); - if (systemConfigurationType == null) { // something really wrong happened (or we are doing initial import of objects) - return; - } - -// boolean specificSecurityPoliciesDefined = false; -// if (systemConfigurationType.getGlobalSecurityPolicyRef() != null) { -// -// SecurityPolicyType securityPolicyType = NotificationFuctionsImpl.getSecurityPolicyConfiguration(systemConfigurationType.getGlobalSecurityPolicyRef(), cacheRepositoryService, result); -// if (securityPolicyType != null && securityPolicyType.getAuthentication() != null) { -// -// for (MailAuthenticationPolicyType mailPolicy : securityPolicyType.getAuthentication().getMailAuthentication()) { -// NotificationConfigurationType notificationConfigurationType = mailPolicy.getNotificationConfiguration(); -// if (notificationConfigurationType != null) { -// specificSecurityPoliciesDefined = true; -// processNotifications(notificationConfigurationType, event, task, result); -// } -// } -// -// for (SmsAuthenticationPolicyType mailPolicy : securityPolicyType.getAuthentication().getSmsAuthentication()) { -// NotificationConfigurationType notificationConfigurationType = mailPolicy.getNotificationConfiguration(); -// if (notificationConfigurationType != null) { -// specificSecurityPoliciesDefined = true; -// processNotifications(notificationConfigurationType, event, task, result); -// } -// } -// -// return; -// } -// } -// -// if (specificSecurityPoliciesDefined) { -// LOGGER.trace("Specific policy for notifier set in security configuration, skupping notifiers defined in system configuration."); -// return; -// } - - if (systemConfigurationType.getNotificationConfiguration() == null) { - LOGGER.trace("No notification configuration in repository, finished event processing."); - return; - } - - NotificationConfigurationType notificationConfigurationType = systemConfigurationType.getNotificationConfiguration(); - processNotifications(notificationConfigurationType, event, task, result); - - LOGGER.trace("NotificationManager successfully processed event {} ({} top level handler(s))", event, notificationConfigurationType.getHandler().size()); } - private void processNotifications(NotificationConfigurationType notificationConfigurationType, Event event, Task task, OperationResult result){ - - - for (EventHandlerType eventHandlerType : notificationConfigurationType.getHandler()) { - processEvent(event, eventHandlerType, task, result); - } - } - - public boolean processEvent(Event event, EventHandlerType eventHandlerType, Task task, OperationResult result) { + @Override + public boolean processEvent(@NotNull Event event, EventHandlerType eventHandlerBean, Task task, OperationResult result) { try { - return getEventHandler(eventHandlerType).processEvent(event, eventHandlerType, this, task, result); - } catch (SchemaException e) { - LoggingUtils.logException(LOGGER, "Event couldn't be processed; event = {}", e, event); - return true; // continue if you can + return eventHandlerRegistry.forwardToHandler(event, eventHandlerBean, task, result); + } catch (Throwable t) { + LoggingUtils.logUnexpectedException(LOGGER, "Event couldn't be processed; event = {}", t, event); + return true; // continue if you can } } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/TransportRegistry.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/TransportRegistry.java new file mode 100644 index 00000000000..59cb2497821 --- /dev/null +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/TransportRegistry.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.notifications.impl; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.notifications.api.transports.Transport; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; + +/** + * + */ +@Component +public class TransportRegistry { + + private static final Trace LOGGER = TraceManager.getTrace(TransportRegistry.class); + + private Map transports = new ConcurrentHashMap<>(); + + public void registerTransport(String name, Transport transport) { + LOGGER.trace("Registering notification transport {} under name {}", transport, name); + transports.put(name, transport); + } + + // accepts name:subname (e.g. dummy:accounts) - a primitive form of passing parameters (will be enhanced/replaced in the future) + public Transport getTransport(String name) { + String key = name.split(":")[0]; + Transport transport = transports.get(key); + if (transport == null) { + throw new IllegalStateException("Unknown transport named " + key); + } else { + return transport; + } + } +} diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/CustomTransport.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/CustomTransport.java index 0b2017acad5..a2e0ad16e0c 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/CustomTransport.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/CustomTransport.java @@ -7,6 +7,7 @@ package com.evolveum.midpoint.notifications.impl.api.transports; +import com.evolveum.midpoint.notifications.impl.TransportRegistry; import com.evolveum.midpoint.repo.common.expression.Expression; import com.evolveum.midpoint.repo.common.expression.ExpressionEvaluationContext; import com.evolveum.midpoint.repo.common.expression.ExpressionFactory; @@ -79,9 +80,11 @@ public class CustomTransport implements Transport { @Autowired private NotificationManager notificationManager; + @Autowired private TransportRegistry transportRegistry; + @PostConstruct public void init() { - notificationManager.registerTransport(NAME, this); + transportRegistry.registerTransport(NAME, this); } @Override diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/FileTransport.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/FileTransport.java index 269061db6a7..4a935b06a05 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/FileTransport.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/FileTransport.java @@ -11,6 +11,7 @@ import com.evolveum.midpoint.notifications.api.events.Event; import com.evolveum.midpoint.notifications.api.transports.Message; import com.evolveum.midpoint.notifications.api.transports.Transport; +import com.evolveum.midpoint.notifications.impl.TransportRegistry; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.result.OperationResult; @@ -41,11 +42,11 @@ public class FileTransport implements Transport { private static final String DEFAULT_FILE_NAME = "notifications.txt"; @Autowired @Qualifier("cacheRepositoryService") private transient RepositoryService cacheRepositoryService; - @Autowired private NotificationManager notificationManager; + @Autowired private TransportRegistry transportRegistry; @PostConstruct public void init() { - notificationManager.registerTransport(NAME, this); + transportRegistry.registerTransport(NAME, this); } @Override diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/MailTransport.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/MailTransport.java index ef0938fe298..837445aa7f9 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/MailTransport.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/MailTransport.java @@ -30,6 +30,8 @@ import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; +import com.evolveum.midpoint.notifications.impl.TransportRegistry; + import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -86,9 +88,11 @@ public class MailTransport implements Transport { @Autowired protected ExpressionFactory expressionFactory; + @Autowired private TransportRegistry transportRegistry; + @PostConstruct public void init() { - notificationManager.registerTransport(NAME, this); + transportRegistry.registerTransport(NAME, this); } @Override diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/SimpleSmsTransport.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/SimpleSmsTransport.java index bcb5186052b..927d9b698bd 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/SimpleSmsTransport.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/api/transports/SimpleSmsTransport.java @@ -7,6 +7,7 @@ package com.evolveum.midpoint.notifications.impl.api.transports; +import com.evolveum.midpoint.notifications.impl.TransportRegistry; import com.evolveum.midpoint.notifications.impl.util.HttpUtil; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.crypto.Protector; @@ -89,7 +90,7 @@ public class SimpleSmsTransport implements Transport { @Autowired protected PrismContext prismContext; @Autowired protected ExpressionFactory expressionFactory; - @Autowired private NotificationManager notificationManager; + @Autowired private TransportRegistry transportRegistry; @Autowired @Qualifier("cacheRepositoryService") private transient RepositoryService cacheRepositoryService; @@ -97,7 +98,7 @@ public class SimpleSmsTransport implements Transport { @PostConstruct public void init() { - notificationManager.registerTransport(NAME, this); + transportRegistry.registerTransport(NAME, this); } @Override diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/formatters/DeltaFormatter.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/formatters/DeltaFormatter.java index 01b953af657..1f3bf4d218b 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/formatters/DeltaFormatter.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/formatters/DeltaFormatter.java @@ -39,8 +39,6 @@ public class DeltaFormatter { @Autowired private ValueFormatter valueFormatter; - @Autowired @Qualifier("cacheRepositoryService") private transient RepositoryService cacheRepositoryService; - @Autowired private PrismContext prismContext; @Autowired protected NotificationFunctionsImpl functions; @Autowired private LocalizationService localizationService; diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/handlers/AggregatedEventHandler.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/handlers/AggregatedEventHandler.java index 1d2ae628022..d1845700940 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/handlers/AggregatedEventHandler.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/handlers/AggregatedEventHandler.java @@ -9,7 +9,7 @@ import com.evolveum.midpoint.notifications.api.NotificationManager; import com.evolveum.midpoint.notifications.api.events.Event; -import com.evolveum.midpoint.notifications.impl.NotificationManagerImpl; +import com.evolveum.midpoint.notifications.impl.EventHandlerRegistry; import com.evolveum.midpoint.notifications.impl.helpers.CategoryFilterHelper; import com.evolveum.midpoint.notifications.impl.helpers.ChainHelper; import com.evolveum.midpoint.notifications.impl.helpers.ExpressionFilterHelper; @@ -37,10 +37,10 @@ * notifiers, and so on). The original plug-in architecture had to be a bit abused because of the notifications * schema change. * - * @author mederly + * TODO should we really extend BaseHandler? E.g. should we register ourselves? (probably not) */ @Component -public class AggregatedEventHandler extends BaseHandler { +public class AggregatedEventHandler extends BaseHandler { private static final Trace LOGGER = TraceManager.getTrace(AggregatedEventHandler.class); @@ -52,55 +52,62 @@ public class AggregatedEventHandler extends BaseHandler { @Autowired private ExpressionFilterHelper expressionFilter; @Autowired private ChainHelper chainHelper; @Autowired private ForkHelper forkHelper; + @Autowired private NotificationManager notificationManager; + @Autowired private EventHandlerRegistry eventHandlerRegistry; - @PostConstruct - public void init() { - register(EventHandlerType.class); + @Override + public Class getEventType() { + return Event.class; + } + + @Override + public Class getEventHandlerConfigurationType() { + return EventHandlerType.class; } @Override - public boolean processEvent(Event event, EventHandlerType eventHandlerType, NotificationManager notificationManager, - Task task, OperationResult result) throws SchemaException { + public boolean processEvent(Event event, EventHandlerType configuration, Task task, OperationResult result) + throws SchemaException { - logStart(LOGGER, event, eventHandlerType); + logStart(LOGGER, event, configuration); boolean shouldContinue = - categoryFilter.processEvent(event, eventHandlerType) && - operationFilter.processEvent(event, eventHandlerType) && - statusFilter.processEvent(event, eventHandlerType) && - kindIntentFilter.processEvent(event, eventHandlerType) && - focusTypeFilterHelper.processEvent(event, eventHandlerType) && - expressionFilter.processEvent(event, eventHandlerType, task, result) && - chainHelper.processEvent(event, eventHandlerType, notificationManager, task, result) && - forkHelper.processEvent(event, eventHandlerType, notificationManager, task, result); - - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getSimpleUserNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getSimpleFocalObjectNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getSimpleResourceObjectNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getSimpleWorkflowNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getSimpleCaseManagementNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getUserPasswordNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getUserRegistrationNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getPasswordResetNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getAccountActivationNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getAccountPasswordNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getGeneralNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getCustomNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getSimpleCampaignNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getSimpleCampaignStageNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getSimpleReviewerNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getSimpleTaskNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getSimpleReportNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getSimplePolicyRuleNotifier(), notificationManager, task, result); - shouldContinue = shouldContinue && processNotifiers(event, eventHandlerType.getTimeValidityNotifier(), notificationManager, task, result); - - logEnd(LOGGER, event, eventHandlerType, shouldContinue); + categoryFilter.processEvent(event, configuration) && + operationFilter.processEvent(event, configuration) && + statusFilter.processEvent(event, configuration) && + kindIntentFilter.processEvent(event, configuration) && + focusTypeFilterHelper.processEvent(event, configuration) && + expressionFilter.processEvent(event, configuration, task, result) && + chainHelper.processEvent(event, configuration, notificationManager, task, result) && + forkHelper.processEvent(event, configuration, notificationManager, task, result); + + shouldContinue = shouldContinue && processNotifiers(event, configuration.getSimpleUserNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getSimpleFocalObjectNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getSimpleResourceObjectNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getSimpleWorkflowNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getSimpleCaseManagementNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getUserPasswordNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getUserRegistrationNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getPasswordResetNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getAccountActivationNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getAccountPasswordNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getGeneralNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getCustomNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getSimpleCampaignNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getSimpleCampaignStageNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getSimpleReviewerNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getSimpleTaskNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getSimpleReportNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getSimplePolicyRuleNotifier(), task, result); + shouldContinue = shouldContinue && processNotifiers(event, configuration.getTimeValidityNotifier(), task, result); + + logEnd(LOGGER, event, shouldContinue); return shouldContinue; } - private boolean processNotifiers(Event event, List notifiers, NotificationManager notificationManager, Task task, OperationResult result) throws SchemaException { + private boolean processNotifiers(Event event, List notifiers, Task task, OperationResult result) throws SchemaException { for (EventHandlerType notifier : notifiers) { - boolean shouldContinue = ((NotificationManagerImpl) notificationManager).getEventHandler(notifier).processEvent(event, notifier, notificationManager, task, result); + boolean shouldContinue = eventHandlerRegistry.forwardToHandler(event, notifier, task, result); if (!shouldContinue) { return false; } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/handlers/BaseHandler.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/handlers/BaseHandler.java index 19b0f6d2fcf..b4c030ba693 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/handlers/BaseHandler.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/handlers/BaseHandler.java @@ -7,6 +7,9 @@ package com.evolveum.midpoint.notifications.impl.handlers; +import com.evolveum.midpoint.model.api.ProgressInformation; +import com.evolveum.midpoint.notifications.api.events.ModelEvent; +import com.evolveum.midpoint.notifications.impl.EventHandlerRegistry; import com.evolveum.midpoint.notifications.impl.formatters.TextFormatter; import com.evolveum.midpoint.notifications.impl.helpers.NotificationExpressionHelper; import com.evolveum.midpoint.repo.common.expression.ExpressionFactory; @@ -27,13 +30,17 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import javax.annotation.PostConstruct; import java.util.*; +import static com.evolveum.midpoint.model.api.ProgressInformation.ActivityType.NOTIFICATIONS; +import static com.evolveum.midpoint.model.api.ProgressInformation.StateType.ENTERING; + /** - * @author mederly + * */ @Component -public abstract class BaseHandler implements EventHandler { +public abstract class BaseHandler implements EventHandler { private static final Trace LOGGER = TraceManager.getTrace(BaseHandler.class); @@ -43,26 +50,28 @@ public abstract class BaseHandler implements EventHandler { @Autowired protected ExpressionFactory expressionFactory; @Autowired protected TextFormatter textFormatter; @Autowired protected NotificationExpressionHelper expressionHelper; + @Autowired protected EventHandlerRegistry eventHandlerRegistry; - protected void register(Class clazz) { - notificationManager.registerEventHandler(clazz, this); + @PostConstruct + protected void register() { + eventHandlerRegistry.registerEventHandler(getEventHandlerConfigurationType(), this); } - protected void logStart(Trace LOGGER, Event event, EventHandlerType eventHandlerType) { - logStart(LOGGER, event, eventHandlerType, null); + protected void logStart(Trace LOGGER, E event, C handlerConfiguration) { + logStart(LOGGER, event, handlerConfiguration, null); } - protected void logStart(Trace LOGGER, Event event, EventHandlerType eventHandlerType, Object additionalData) { + protected void logStart(Trace LOGGER, E event, C handlerConfiguration, Object additionalData) { if (LOGGER.isTraceEnabled()) { LOGGER.trace("Starting processing event " + event.shortDump() + " with handler " + - getHumanReadableHandlerDescription(eventHandlerType) + "\n parameters: " + + getHumanReadableHandlerDescription(handlerConfiguration) + "\n parameters: " + (additionalData != null ? ("\n parameters: " + additionalData) : - ("\n configuration: " + eventHandlerType))); + ("\n configuration: " + handlerConfiguration))); } } - protected void logNotApplicable(Event event, String reason) { + protected void logNotApplicable(E event, String reason) { if (LOGGER.isTraceEnabled()) { LOGGER.trace( "{} is not applicable for event {}, continuing in the handler chain; reason: {}", @@ -70,26 +79,16 @@ protected void logNotApplicable(Event event, String reason) { } } - protected String getHumanReadableHandlerDescription(EventHandlerType eventHandlerType) { - if (eventHandlerType.getName() != null) { - return eventHandlerType.getName(); + protected String getHumanReadableHandlerDescription(C handlerConfiguration) { + if (handlerConfiguration.getName() != null) { + return handlerConfiguration.getName(); } else { - return eventHandlerType.getClass().getSimpleName(); + return handlerConfiguration.getClass().getSimpleName(); } } - public static void staticLogStart(Trace LOGGER, Event event, String description, Object additionalData) { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Starting processing event " + event + " with handler " + - description + - (additionalData != null ? (", parameters: " + additionalData) : "")); - } - } - - public void logEnd(Trace LOGGER, Event event, EventHandlerType eventHandlerType, boolean result) { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Finishing processing event " + event + " result = " + result); - } + public void logEnd(Trace logger, E event, boolean result) { + logger.trace("Finishing processing event {}, result = {}", event, result); } protected List evaluateExpressionChecked(ExpressionType expressionType, ExpressionVariables expressionVariables, @@ -102,7 +101,19 @@ protected List evaluateNotificationMessageAtt return expressionHelper.evaluateNotificationMessageAttachmentTypeExpressionChecked(expressionType, expressionVariables, shortDesc, task, result); } - protected ExpressionVariables getDefaultVariables(Event event, OperationResult result) { + protected ExpressionVariables getDefaultVariables(E event, OperationResult result) { return expressionHelper.getDefaultVariables(event, result); } + + protected void reportNotificationStart(E event) { + if (event instanceof ModelEvent) { + ((ModelEvent) event).getModelContext().reportProgress(new ProgressInformation(NOTIFICATIONS, ENTERING)); + } + } + + protected void reportNotificationEnd(E event, OperationResult result) { + if (event instanceof ModelEvent) { + ((ModelEvent) event).getModelContext().reportProgress(new ProgressInformation(NOTIFICATIONS, result)); + } + } } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/AbstractFocalObjectNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/AbstractFocalObjectNotifier.java new file mode 100644 index 00000000000..b68038a96a8 --- /dev/null +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/AbstractFocalObjectNotifier.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2010-2013 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.notifications.impl.notifiers; + +import static com.evolveum.midpoint.util.MiscUtil.emptyIfNull; + +import java.util.Date; +import java.util.List; + +import org.jetbrains.annotations.Nullable; +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.model.api.context.ModelContext; +import com.evolveum.midpoint.model.api.context.ModelElementContext; +import com.evolveum.midpoint.notifications.api.events.ModelEvent; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.delta.ObjectDeltaCollectionsUtil; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SimpleFocalObjectNotifierType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; + +/** + * + */ +@Component +public abstract class AbstractFocalObjectNotifier extends AbstractGeneralNotifier { + + private static final Trace LOGGER = TraceManager.getTrace(AbstractFocalObjectNotifier.class); + + @Override + public Class getEventType() { + return ModelEvent.class; + } + + abstract Class getFocusClass(); + + @Override + protected boolean quickCheckApplicability(ModelEvent event, SimpleFocalObjectNotifierType configuration, OperationResult result) { + if (event.getFocusContext() == null || !event.getFocusContext().isOfType(getFocusClass())) { + LOGGER.trace("{} is not applicable to non-{} related model operations, continuing in the handler chain", + getClass().getSimpleName(), getFocusClass()); + return false; + } else { + return true; + } + } + + @Override + protected boolean checkApplicability(ModelEvent event, C configuration, OperationResult result) { + List> deltas = event.getFocusDeltas(); + if (deltas.isEmpty()) { + LOGGER.trace("No deltas found, skipping the notification"); + return false; + } else if (isWatchAuxiliaryAttributes(configuration)) { + return true; + } else { + for (ObjectDelta delta : deltas) { + if (!delta.isModify() || deltaContainsOtherPathsThan(delta, functions.getAuxiliaryPaths())) { + return true; + } + } + LOGGER.trace("No deltas for non-auxiliary attributes found, skipping the notification"); + return false; + } + } + + @Override + protected String getSubject(ModelEvent event, C configuration, String transport, Task task, OperationResult result) { + + String typeName = event.getFocusTypeName(); + + if (event.isAdd()) { + return typeName + " creation notification"; + } else if (event.isModify()) { + return typeName + " modification notification"; + } else if (event.isDelete()) { + return typeName + " deletion notification"; + } else { + return "(unknown " + typeName.toLowerCase() + " operation)"; + } + } + + @Override + protected String getBody(ModelEvent modelEvent, C configuration, String transport, + Task task, OperationResult result) throws SchemaException { + + String typeName = modelEvent.getFocusTypeName(); + String typeNameLower = typeName.toLowerCase(); + + boolean techInfo = Boolean.TRUE.equals(configuration.isShowTechnicalInformation()); + + //noinspection unchecked + ModelContext modelContext = (ModelContext) modelEvent.getModelContext(); + ModelElementContext focusContext = modelContext.getFocusContext(); + PrismObject focusObject = focusContext.getObjectNew() != null ? focusContext.getObjectNew() : focusContext.getObjectOld(); + FocusType focus = focusObject.asObjectable(); + String oid = focusContext.getOid(); + + String fullName = emptyIfNull(getFullName(focus)); + + ObjectDelta delta = ObjectDeltaCollectionsUtil.summarize(modelEvent.getFocusDeltas()); + + StringBuilder body = new StringBuilder(); + + String status = modelEvent.getStatusAsText(); + String attemptedTo = modelEvent.isSuccess() ? "" : "(attempted to be) "; + + body.append("Notification about ").append(typeNameLower).append("-related operation (status: ").append(status).append(")\n\n"); + body.append(typeName).append(": ").append(fullName).append(" (").append(focus.getName()).append(", oid ").append(oid).append(")\n"); + body.append("Notification created on: ").append(new Date()).append("\n\n"); + + final boolean watchAuxiliaryAttributes = isWatchAuxiliaryAttributes(configuration); + if (delta.isAdd()) { + body.append("The ").append(typeNameLower).append(" record was ").append(attemptedTo).append("created with the following data:\n"); + body.append(modelEvent.getContentAsFormattedList(false, watchAuxiliaryAttributes)); + } else if (delta.isModify()) { + body.append("The ").append(typeNameLower).append(" record was ").append(attemptedTo).append("modified. Modified attributes are:\n"); + body.append(modelEvent.getContentAsFormattedList(false, watchAuxiliaryAttributes)); + } else if (delta.isDelete()) { + body.append("The ").append(typeNameLower).append(" record was ").append(attemptedTo).append("removed.\n"); + } + body.append("\n"); + + if (!modelEvent.isSuccess()) { + body.append("More information about the status of the request was displayed and/or is present in log files.\n\n"); + } + + functions.addRequesterAndChannelInformation(body, modelEvent, result); + + if (techInfo) { + body.append("----------------------------------------\n"); + body.append("Technical information:\n\n"); + body.append(modelContext.debugDump(2)); + } + + return body.toString(); + } + + @Nullable + private String getFullName(FocusType focus) { + String fullName; + if (focus instanceof UserType) { + fullName = PolyString.getOrig(((UserType) focus).getFullName()); + } else if (focus instanceof AbstractRoleType) { + fullName = PolyString.getOrig(((AbstractRoleType) focus).getDisplayName()); + } else { + fullName = ""; // TODO (currently it's not possible to get here) + } + return fullName; + } + + @Override + protected Trace getLogger() { + return LOGGER; + } +} diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/AbstractGeneralNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/AbstractGeneralNotifier.java new file mode 100644 index 00000000000..67224c02b75 --- /dev/null +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/AbstractGeneralNotifier.java @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.notifications.impl.notifiers; + +import com.evolveum.midpoint.notifications.impl.TransportRegistry; +import com.evolveum.midpoint.notifications.impl.formatters.ValueFormatter; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.repo.common.expression.ExpressionVariables; +import com.evolveum.midpoint.notifications.api.NotificationManager; +import com.evolveum.midpoint.notifications.api.events.Event; +import com.evolveum.midpoint.notifications.api.events.SimpleObjectRef; +import com.evolveum.midpoint.notifications.api.transports.Message; +import com.evolveum.midpoint.notifications.api.transports.Transport; +import com.evolveum.midpoint.notifications.impl.NotificationFunctionsImpl; +import com.evolveum.midpoint.notifications.impl.formatters.TextFormatter; +import com.evolveum.midpoint.notifications.impl.handlers.AggregatedEventHandler; +import com.evolveum.midpoint.notifications.impl.handlers.BaseHandler; +import com.evolveum.midpoint.prism.delta.ItemDelta; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.schema.constants.ExpressionConstants; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.result.OperationResultStatus; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import org.apache.cxf.common.util.StringUtils; +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * + */ +@Component +public abstract class AbstractGeneralNotifier extends BaseHandler { + + private static final Trace DEFAULT_LOGGER = TraceManager.getTrace(AbstractGeneralNotifier.class); + + private static final String OP_PROCESS_EVENT = AbstractGeneralNotifier.class.getName() + ".processEvent"; + private static final String OP_PREPARE_AND_SEND = AbstractGeneralNotifier.class.getName() + ".prepareAndSend"; + + @Autowired protected NotificationManager notificationManager; + @Autowired protected NotificationFunctionsImpl functions; + @Autowired protected TextFormatter textFormatter; + @Autowired protected ValueFormatter valueFormatter; + @Autowired protected AggregatedEventHandler aggregatedEventHandler; + @Autowired protected TransportRegistry transportRegistry; + + @Override + public boolean processEvent(E event, N notifierConfiguration, Task task, OperationResult parentResult) + throws SchemaException { + + OperationResult result = parentResult.subresult(OP_PROCESS_EVENT) + .setMinor() + .addContext("notifier", this.getClass().getName()) + .build(); + int messagesSent = 0; + try { + logStart(getLogger(), event, notifierConfiguration); + + boolean applies = aggregatedEventHandler.processEvent(event, notifierConfiguration, task, result); + if (applies) { + if (!quickCheckApplicability(event, notifierConfiguration, result)) { + // nothing to do -- an appropriate message should have been logged in quickCheckApplicability method + result.recordNotApplicable(); + } else if (!checkApplicability(event, notifierConfiguration, result)) { + // nothing to do -- an appropriate message should have been logged in checkApplicability method + result.recordNotApplicable(); + } else if (notifierConfiguration.getTransport().isEmpty()) { + getLogger().warn("No transports for this notifier, exiting without sending any notifications."); + result.recordStatus(OperationResultStatus.NOT_APPLICABLE, "No transports"); + } else { + reportNotificationStart(event); + try { + ExpressionVariables variables = getDefaultVariables(event, result); + for (String transportName : notifierConfiguration.getTransport()) { + messagesSent += prepareAndSend(event, notifierConfiguration, variables, transportName, task, result); + } + } finally { + reportNotificationEnd(event, result); + } + } + } + logEnd(getLogger(), event, applies); + return true; // not-applicable notifiers do not stop processing of other notifiers + } catch (Throwable t) { + result.recordFatalError(t); + throw t; + } finally { + result.addReturn("messagesSent", messagesSent); + result.computeStatusIfUnknown(); + } + } + + private int prepareAndSend(E event, N notifierConfig, ExpressionVariables variables, String transportName, + Task task, OperationResult parentResult) throws SchemaException { + OperationResult result = parentResult.subresult(OP_PREPARE_AND_SEND) + .setMinor() + .addParam("transportName", transportName) + .addContext("notifier", this.getClass().getName()) + .build(); + try { + variables.put(ExpressionConstants.VAR_TRANSPORT_NAME, transportName, String.class); + Transport transport = transportRegistry.getTransport(transportName); + + List recipientsAddresses = getRecipientsAddresses(event, notifierConfig, variables, + getDefaultRecipient(event, notifierConfig, result), transportName, transport, task, result); + result.addArbitraryObjectCollectionAsContext("recipientAddress", recipientsAddresses); + + if (!recipientsAddresses.isEmpty()) { + + String body; + ExpressionType bodyExpression = notifierConfig.getBodyExpression(); + if (bodyExpression != null) { + body = getBodyFromExpression(event, bodyExpression, variables, task, result); + } else { + body = getBody(event, notifierConfig, transportName, task, result); + } + if (body == null) { + getLogger().debug("Skipping notification as null body was provided for transport={}", transportName); + result.recordStatus(OperationResultStatus.NOT_APPLICABLE, "No message body"); + return 0; + } + + String from = getFromFromExpression(event, notifierConfig, variables, task, result); + String contentType = getContentTypeFromExpression(event, notifierConfig, variables, task, result); + List attachments = getAttachmentsFromExpression(event, notifierConfig, variables, task, result); + + String subject = getSubjectFromExpression(event, notifierConfig, variables, task, result); + if (subject == null) { + subject = notifierConfig.getSubjectPrefix() != null ? notifierConfig.getSubjectPrefix() : ""; + subject += getSubject(event, notifierConfig, transportName, task, result); + } + + if (attachments == null) { + attachments = notifierConfig.getAttachment(); + if (attachments == null) { + attachments = getAttachment(event, notifierConfig, transportName, task, result); + } + } else if (notifierConfig.getAttachment() != null) { + attachments.addAll(notifierConfig.getAttachment()); + } + + Message message = new Message(); + message.setBody(body); + if (contentType != null) { + message.setContentType(contentType); + } else if (notifierConfig.getContentType() != null) { + message.setContentType(notifierConfig.getContentType()); + } else if (getContentType() != null) { + message.setContentType(getContentType()); + } + message.setSubject(subject); + + if (from != null) { + message.setFrom(from); + } + message.setTo(recipientsAddresses); + message.setCc(getCcBccAddresses(notifierConfig.getCcExpression(), variables, "notification cc-expression", task, result)); + message.setBcc(getCcBccAddresses(notifierConfig.getBccExpression(), variables, "notification bcc-expression", task, result)); + + if (attachments != null) { + message.setAttachments(attachments); + } + + getLogger().trace("Sending notification via transport {}:\n{}", transportName, message); + transport.send(message, transportName, event, task, result); + return 1; // TODO only if really sent + } else { + getLogger().info("No recipients addresses for transport " + transportName + ", message corresponding to event " + event.getId() + " will not be send."); + result.recordStatus(OperationResultStatus.NOT_APPLICABLE, "No recipients"); + return 0; + } + } catch (Throwable t) { + result.recordFatalError(t); + throw t; + } finally { + result.computeStatusIfUnknown(); + } + } + + protected String getContentType() { + return null; + } + + protected boolean quickCheckApplicability(E event, N generalNotifierType, OperationResult result) { + return true; + } + + protected boolean checkApplicability(E event, N generalNotifierType, OperationResult result) { + return true; + } + + protected String getSubject(E event, N generalNotifierType, String transport, Task task, OperationResult result) { + return null; + } + + protected String getBody(E event, N generalNotifierType, String transport, Task task, OperationResult result) throws SchemaException { + return null; + } + + // for future extension + @SuppressWarnings("unused") + private List getAttachment(E event, N generalNotifierType, + String transportName, Task task, OperationResult result) { + return null; + } + + protected UserType getDefaultRecipient(E event, N generalNotifierType, OperationResult result) { + ObjectType objectType = functions.getObjectType(event.getRequestee(), true, result); + if (objectType instanceof UserType) { + return (UserType) objectType; + } else { + return null; + } + } + + protected Trace getLogger() { + return DEFAULT_LOGGER; // in case a subclass does not provide its own logger + } + + private List getRecipientsAddresses(E event, N generalNotifierType, ExpressionVariables variables, + UserType defaultRecipient, String transportName, Transport transport, Task task, OperationResult result) { + List addresses = new ArrayList<>(); + if (!generalNotifierType.getRecipientExpression().isEmpty()) { + for (ExpressionType expressionType : generalNotifierType.getRecipientExpression()) { + List r = evaluateExpressionChecked(expressionType, variables, "notification recipient", task, result); + if (r != null) { + addresses.addAll(r); + } + } + if (addresses.isEmpty()) { + getLogger().info("Notification for " + event + " will not be sent, because there are no known recipients."); + } + } else if (defaultRecipient == null) { + getLogger().info("Unknown default recipient, notification will not be sent."); + } else { + String address = transport.getDefaultRecipientAddress(defaultRecipient); + if (StringUtils.isEmpty(address)) { + getLogger().info("Notification to " + defaultRecipient.getName() + " will not be sent, because the user has no address (mail, phone number, etc) for transport '" + transportName + "' set."); + } else { + addresses.add(address); + } + } + return addresses; + } + + @NotNull + private List getCcBccAddresses(List expressions, ExpressionVariables variables, + String shortDesc, Task task, OperationResult result) { + List addresses = new ArrayList<>(); + for (ExpressionType expressionType : expressions) { + List r = evaluateExpressionChecked(expressionType, variables, shortDesc, task, result); + if (r != null) { + addresses.addAll(r); + } + } + return addresses; + } + + private String getSubjectFromExpression(E event, N generalNotifierType, ExpressionVariables variables, + Task task, OperationResult result) { + return getStringFromExpression(event, variables, task, result, generalNotifierType.getSubjectExpression(), "subject", false); + } + + private String getFromFromExpression(E event, N generalNotifierType, ExpressionVariables variables, + Task task, OperationResult result) { + return getStringFromExpression(event, variables, task, result, generalNotifierType.getFromExpression(), "from", true); + } + + private String getContentTypeFromExpression(E event, N generalNotifierType, ExpressionVariables variables, + Task task, OperationResult result) { + return getStringFromExpression(event, variables, task, result, generalNotifierType.getContentTypeExpression(), "contentType", true); + } + + private String getStringFromExpression(E event, ExpressionVariables variables, + Task task, OperationResult result, ExpressionType expression, String expressionTypeName, boolean canBeNull) { + if (expression != null) { + List contentTypeList = evaluateExpressionChecked(expression, variables, expressionTypeName + " expression", + task, result); + if (contentTypeList == null || contentTypeList.isEmpty()) { + getLogger().info(expressionTypeName + " expression for event " + event.getId() + " returned nothing."); + return canBeNull ? null : ""; + } + if (contentTypeList.size() > 1) { + getLogger().warn(expressionTypeName + " expression for event " + event.getId() + " returned more than 1 item."); + } + return contentTypeList.get(0); + } else { + return null; + } + } + + private String getBodyFromExpression(E event, @NotNull ExpressionType bodyExpression, ExpressionVariables variables, + Task task, OperationResult result) { + List bodyList = evaluateExpressionChecked(bodyExpression, variables, + "body expression", task, result); + if (bodyList == null || bodyList.isEmpty()) { + getLogger().warn("Body expression for event {} returned nothing.", event.getId()); + return null; + } else { + StringBuilder body = new StringBuilder(); + for (String s : bodyList) { + body.append(s); + } + return body.toString(); + } + } + + private List getAttachmentsFromExpression(E event, N generalNotifierType, ExpressionVariables variables, + Task task, OperationResult result) { + if (generalNotifierType.getAttachmentExpression() != null) { + List attachment = evaluateNotificationMessageAttachmentTypeExpressionChecked(generalNotifierType.getAttachmentExpression(), variables, "contentType expression", + task, result); + if (attachment == null) { + getLogger().info("attachment expression for event " + event.getId() + " returned nothing."); + return null; + } + return attachment; + } else { + return null; + } + } + + // TODO implement more efficiently + // precondition: delta is MODIFY delta + boolean deltaContainsOtherPathsThan(ObjectDelta delta, List paths) { + for (ItemDelta itemDelta : delta.getModifications()) { + if (!NotificationFunctionsImpl.isAmongHiddenPaths(itemDelta.getPath(), paths)) { + return true; + } + } + return false; + } + + boolean isWatchAuxiliaryAttributes(N configuration) { + return Boolean.TRUE.equals((configuration).isWatchAuxiliaryAttributes()); + } + + String formatRequester(E event, OperationResult result) { + SimpleObjectRef requesterRef = event.getRequester(); + if (requesterRef == null) { + return "(unknown or none)"; + } + ObjectType requester = requesterRef.resolveObjectType(result, false); + String name = PolyString.getOrig(requester.getName()); + if (requester instanceof UserType) { + return name + " (" + PolyString.getOrig(((UserType) requester).getFullName()) + ")"; + } else { + return name; + } + } +} diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/AbstractPolicyRuleNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/AbstractPolicyRuleNotifier.java new file mode 100644 index 00000000000..4ad44a9f410 --- /dev/null +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/AbstractPolicyRuleNotifier.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2010-2017 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.notifications.impl.notifiers; + +import org.springframework.stereotype.Component; + +import com.evolveum.midpoint.notifications.api.events.PolicyRuleEvent; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SimplePolicyRuleNotifierType; + +/** + * + */ +@Component +public abstract class AbstractPolicyRuleNotifier extends AbstractGeneralNotifier { + + @Override + public Class getEventType() { + return PolicyRuleEvent.class; + } + + @Override + protected String getSubject(PolicyRuleEvent event, SimplePolicyRuleNotifierType configuration, String transport, Task task, OperationResult result) { + return "Policy rule '" + event.getRuleName() + "' triggering notification"; + } + + @Override + protected String getBody(PolicyRuleEvent event, SimplePolicyRuleNotifierType configuration, String transport, Task opTask, OperationResult opResult) throws SchemaException { + return "Notification about policy rule-related event.\n\n" + // TODO TODO TODO + + event.getPolicyRule().debugDump(); + } +} diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/AccountActivationNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/AccountActivationNotifier.java index 23bf90b80aa..2e84ce3e169 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/AccountActivationNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/AccountActivationNotifier.java @@ -26,13 +26,13 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; @Component -public class AccountActivationNotifier extends ConfirmationNotifier { +public class AccountActivationNotifier extends ConfirmationNotifier { private static final Trace LOGGER = TraceManager.getTrace(AccountActivationNotifier.class); @Override - public void init() { - register(AccountActivationNotifierType.class); + public Class getEventHandlerConfigurationType() { + return AccountActivationNotifierType.class; } @Override @@ -41,40 +41,37 @@ protected Trace getLogger() { } @Override - protected boolean checkApplicability(Event event, GeneralNotifierType generalNotifierType, + protected boolean checkApplicability(ModelEvent event, AccountActivationNotifierType configuration, OperationResult result) { if (!event.isSuccess()) { logNotApplicable(event, "operation was not successful"); return false; } - ModelEvent modelEvent = (ModelEvent) event; - if (modelEvent.getFocusDeltas().isEmpty()) { + if (event.getFocusDeltas().isEmpty()) { logNotApplicable(event, "no user deltas in event"); return false; } - List shadows = getShadowsToActivate(modelEvent); - + List shadows = getShadowsToActivate(event); if (shadows.isEmpty()) { logNotApplicable(event, "no shadows to activate found in model context"); return false; + } else { + LOGGER.trace("Found shadows to activate: {}. Processing notifications.", shadows); + return true; } - - LOGGER.trace("Found shadows to activate: {}. Processing notifications.", shadows); - return true; } - @Override - protected String getSubject(Event event, GeneralNotifierType generalNotifierType, String transport, + protected String getSubject(ModelEvent event, AccountActivationNotifierType configuration, String transport, Task task, OperationResult result) { return "Activate your accounts"; } @Override - protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, - Task task, OperationResult result) throws SchemaException { + protected String getBody(ModelEvent event, AccountActivationNotifierType configuration, String transport, + Task task, OperationResult result) { String message = "Your accounts was successfully created. To activate your accounts, please click on the link bellow."; @@ -83,9 +80,7 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S accountsToActivate = accountsToActivate + shadow.asPrismObject().debugDump() + "\n"; } - String body = message + "\n\n" + createConfirmationLink(getUser(event), generalNotifierType, result) + "\n\n" + accountsToActivate; - - return body; + return message + "\n\n" + createConfirmationLink(getUser(event), configuration, result) + "\n\n" + accountsToActivate; } private List getShadowsToActivate(ModelEvent modelEvent) { diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/AccountPasswordNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/AccountPasswordNotifier.java index 8d0e074f1c8..196851da1fc 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/AccountPasswordNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/AccountPasswordNotifier.java @@ -7,8 +7,6 @@ package com.evolveum.midpoint.notifications.impl.notifiers; -import com.evolveum.midpoint.model.api.expr.MidpointFunctions; -import com.evolveum.midpoint.notifications.api.events.Event; import com.evolveum.midpoint.notifications.api.events.ResourceObjectEvent; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.schema.result.OperationResult; @@ -16,73 +14,51 @@ import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccountPasswordNotifierType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; - -/** - * @author mederly - */ @Component -public class AccountPasswordNotifier extends GeneralNotifier { +public class AccountPasswordNotifier extends AbstractGeneralNotifier { private static final Trace LOGGER = TraceManager.getTrace(AccountPasswordNotifier.class); - private static final Integer LEVEL_TECH_INFO = 10; - - @Autowired - private MidpointFunctions midpointFunctions; - @PostConstruct - public void init() { - register(AccountPasswordNotifierType.class); + @Override + public Class getEventType() { + return ResourceObjectEvent.class; } @Override - protected boolean quickCheckApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - if (!(event instanceof ResourceObjectEvent)) { - LOGGER.trace("AccountPasswordNotifier is not applicable for this kind of event, continuing in the handler chain; event class = " + event.getClass()); - return false; - } else { - return true; - } + public Class getEventHandlerConfigurationType() { + return AccountPasswordNotifierType.class; } @Override - protected boolean checkApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { + protected boolean checkApplicability(ResourceObjectEvent event, AccountPasswordNotifierType configuration, OperationResult result) { if (!event.isSuccess()) { LOGGER.trace("Operation was not successful, exiting."); return false; + } else { + ObjectDelta delta = event.getAccountOperationDescription().getObjectDelta(); + return delta != null && functions.getPlaintextPasswordFromDelta(delta) != null; } - - ResourceObjectEvent resourceObjectEvent = (ResourceObjectEvent) event; - ObjectDelta delta = resourceObjectEvent.getAccountOperationDescription().getObjectDelta(); - if (delta == null) { // should not occur - LOGGER.trace("Object delta is null, exiting. Event = " + event); - return false; - } - return functions.getPlaintextPasswordFromDelta(delta) != null; } @Override - protected String getSubject(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { + protected String getSubject(ResourceObjectEvent event, AccountPasswordNotifierType configuration, String transport, Task task, OperationResult result) { return "Account password notification"; } @Override - protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { + protected String getBody(ResourceObjectEvent event, AccountPasswordNotifierType configuration, String transport, Task task, OperationResult result) { StringBuilder body = new StringBuilder(); - ResourceObjectEvent resourceObjectEvent = (ResourceObjectEvent) event; body.append("Password for account "); - String name = resourceObjectEvent.getShadowName(); + String name = event.getShadowName(); if (name != null) { body.append(name).append(" "); } - body.append("on ").append(resourceObjectEvent.getResourceName()); - body.append(" is: ").append(resourceObjectEvent.getPlaintextPassword()); + body.append("on ").append(event.getResourceName()); + body.append(" is: ").append(event.getPlaintextPassword()); return body.toString(); } @@ -90,5 +66,4 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S protected Trace getLogger() { return LOGGER; } - } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/ConfirmationNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/ConfirmationNotifier.java index a75b3de95fa..e96d5696027 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/ConfirmationNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/ConfirmationNotifier.java @@ -7,23 +7,18 @@ package com.evolveum.midpoint.notifications.impl.notifiers; -import javax.annotation.PostConstruct; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.evolveum.midpoint.model.api.expr.MidpointFunctions; import com.evolveum.midpoint.model.impl.expr.ExpressionEnvironment; import com.evolveum.midpoint.model.impl.expr.ModelExpressionThreadLocalHolder; -import com.evolveum.midpoint.notifications.api.events.Event; import com.evolveum.midpoint.notifications.api.events.ModelEvent; -import com.evolveum.midpoint.notifications.impl.NotificationFunctionsImpl; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ConfirmationNotifierType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.RegistrationConfirmationMethodType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; @@ -31,86 +26,58 @@ * @author katkav */ @Component -public class ConfirmationNotifier extends GeneralNotifier { +public abstract class ConfirmationNotifier extends AbstractGeneralNotifier { private static final Trace LOGGER = TraceManager.getTrace(ConfirmationNotifier.class); - @Autowired - private MidpointFunctions midpointFunctions; - - @Autowired - private NotificationFunctionsImpl notificationsUtil; - - - @PostConstruct - public void init() { - register(ConfirmationNotifierType.class); - } + @Autowired private MidpointFunctions midpointFunctions; @Override - protected boolean quickCheckApplicability(Event event, GeneralNotifierType generalNotifierType, - OperationResult result) { - if (!(event instanceof ModelEvent)) { - logNotApplicable(event, "wrong event type"); - return false; - } else { - return true; - } + public Class getEventType() { + return ModelEvent.class; } public String getConfirmationLink(UserType userType) { throw new UnsupportedOperationException("Please implement in concrete notifier"); } - protected String createConfirmationLink(UserType userType, GeneralNotifierType generalNotifierType, OperationResult result) { - - - ConfirmationNotifierType userRegistrationNotifier = (ConfirmationNotifierType) generalNotifierType; - - RegistrationConfirmationMethodType confirmationMethod = userRegistrationNotifier.getConfirmationMethod(); + String createConfirmationLink(UserType userType, N config, OperationResult result) { + RegistrationConfirmationMethodType confirmationMethod = config.getConfirmationMethod(); if (confirmationMethod == null) { return null; } - ExpressionEnvironment expressionEnv = new ExpressionEnvironment(); + ExpressionEnvironment expressionEnv = new ExpressionEnvironment<>(); expressionEnv.setCurrentResult(result); ModelExpressionThreadLocalHolder.pushExpressionEnvironment(expressionEnv); try { - switch (confirmationMethod) { case LINK: - String confirmationLink = getConfirmationLink(userType); - return confirmationLink; + return getConfirmationLink(userType); case PIN: throw new UnsupportedOperationException("PIN confirmation not supported yes"); // return getNonce(userType); default: - break; + return null; } - } finally { ModelExpressionThreadLocalHolder.popExpressionEnvironment(); } - - return null; - } - protected UserType getUser(Event event){ - ModelEvent modelEvent = (ModelEvent) event; + protected UserType getUser(ModelEvent event) { //noinspection unchecked - PrismObject newUser = (PrismObject) modelEvent.getFocusContext().getObjectNew(); + PrismObject newUser = (PrismObject) event.getFocusContext().getObjectNew(); return newUser.asObjectable(); } - @Override protected Trace getLogger() { return LOGGER; } - public MidpointFunctions getMidpointFunctions() { + MidpointFunctions getMidpointFunctions() { return midpointFunctions; } } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/CustomNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/CustomNotifier.java index d9d45613d4e..afa5428d95f 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/CustomNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/CustomNotifier.java @@ -7,17 +7,21 @@ package com.evolveum.midpoint.notifications.impl.notifiers; -import com.evolveum.midpoint.model.api.ProgressInformation; -import com.evolveum.midpoint.repo.common.expression.Expression; -import com.evolveum.midpoint.repo.common.expression.ExpressionEvaluationContext; -import com.evolveum.midpoint.repo.common.expression.ExpressionVariables; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import javax.xml.namespace.QName; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.model.impl.expr.ModelExpressionThreadLocalHolder; import com.evolveum.midpoint.notifications.api.NotificationManager; import com.evolveum.midpoint.notifications.api.events.Event; -import com.evolveum.midpoint.notifications.api.events.ModelEvent; import com.evolveum.midpoint.notifications.api.transports.Message; import com.evolveum.midpoint.notifications.api.transports.Transport; import com.evolveum.midpoint.notifications.impl.NotificationFunctionsImpl; +import com.evolveum.midpoint.notifications.impl.TransportRegistry; import com.evolveum.midpoint.notifications.impl.api.transports.CustomTransport; import com.evolveum.midpoint.notifications.impl.formatters.TextFormatter; import com.evolveum.midpoint.notifications.impl.handlers.AggregatedEventHandler; @@ -25,93 +29,68 @@ import com.evolveum.midpoint.prism.PrismPropertyDefinition; import com.evolveum.midpoint.prism.PrismPropertyValue; import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple; +import com.evolveum.midpoint.repo.common.expression.Expression; +import com.evolveum.midpoint.repo.common.expression.ExpressionEvaluationContext; +import com.evolveum.midpoint.repo.common.expression.ExpressionVariables; import com.evolveum.midpoint.schema.constants.ExpressionConstants; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.MiscSchemaUtil; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.CommunicationException; -import com.evolveum.midpoint.util.exception.ConfigurationException; -import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SecurityViolationException; -import com.evolveum.midpoint.util.exception.SystemException; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.CustomNotifierType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.EventHandlerType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.NotificationMessageType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; -import javax.xml.namespace.QName; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import static com.evolveum.midpoint.model.api.ProgressInformation.ActivityType.NOTIFICATIONS; -import static com.evolveum.midpoint.model.api.ProgressInformation.StateType.ENTERING; - -/** - * @author mederly - */ @Component -public class CustomNotifier extends BaseHandler { +public class CustomNotifier extends BaseHandler { private static final Trace DEFAULT_LOGGER = TraceManager.getTrace(CustomNotifier.class); - @Autowired - protected NotificationManager notificationManager; - - @Autowired - protected NotificationFunctionsImpl notificationsUtil; + @Autowired protected NotificationManager notificationManager; + @Autowired protected NotificationFunctionsImpl notificationsUtil; + @Autowired protected TextFormatter textFormatter; + @Autowired protected AggregatedEventHandler aggregatedEventHandler; + @Autowired private CustomTransport customTransport; + @Autowired private TransportRegistry transportRegistry; - @Autowired - protected TextFormatter textFormatter; - - @Autowired - protected AggregatedEventHandler aggregatedEventHandler; - - @Autowired - private CustomTransport customTransport; + @Override + public Class getEventType() { + return Event.class; + } - @PostConstruct - public void init() { - register(CustomNotifierType.class); + @Override + public Class getEventHandlerConfigurationType() { + return CustomNotifierType.class; } @Override - public boolean processEvent(Event event, EventHandlerType eventHandlerType, NotificationManager notificationManager, + public boolean processEvent(Event event, CustomNotifierType configuration, Task task, OperationResult parentResult) throws SchemaException { OperationResult result = parentResult.createMinorSubresult(CustomNotifier.class.getName() + ".processEvent"); - logStart(getLogger(), event, eventHandlerType); + logStart(getLogger(), event, configuration); - boolean applies = aggregatedEventHandler.processEvent(event, eventHandlerType, notificationManager, task, result); + boolean applies = aggregatedEventHandler.processEvent(event, configuration, task, result); if (applies) { - CustomNotifierType config = (CustomNotifierType) eventHandlerType; ExpressionVariables variables = getDefaultVariables(event, result); - if (event instanceof ModelEvent) { - ((ModelEvent) event).getModelContext().reportProgress(new ProgressInformation(NOTIFICATIONS, ENTERING)); - } - - List transports = new ArrayList<>(config.getTransport()); + List transports = new ArrayList<>(configuration.getTransport()); if (transports.isEmpty()) { transports.add(customTransport.getName()); } + reportNotificationStart(event); try { - for (String transportName : config.getTransport()) { + for (String transportName : configuration.getTransport()) { variables.put(ExpressionConstants.VAR_TRANSPORT_NAME, transportName, String.class); - Transport transport = notificationManager.getTransport(transportName); + Transport transport = transportRegistry.getTransport(transportName); - Message message = getMessageFromExpression(config, variables, task, result); + Message message = getMessageFromExpression(configuration, variables, task, result); if (message != null) { getLogger().trace("Sending notification via transport {}:\n{}", transportName, message); transport.send(message, transportName, event, task, result); @@ -120,13 +99,10 @@ public boolean processEvent(Event event, EventHandlerType eventHandlerType, Noti } } } finally { - if (event instanceof ModelEvent) { - ((ModelEvent) event).getModelContext().reportProgress( - new ProgressInformation(NOTIFICATIONS, result)); - } + reportNotificationEnd(event, result); } } - logEnd(getLogger(), event, eventHandlerType, applies); + logEnd(getLogger(), event, applies); result.computeStatusIfUnknown(); return true; // not-applicable notifiers do not stop processing of other notifiers } @@ -155,6 +131,7 @@ private Message getMessageFromExpression(CustomNotifierType config, ExpressionVa return messages.get(0) != null ? new Message(messages.get(0)) : null; } + @SuppressWarnings("SameParameterValue") private List evaluateExpression(ExpressionType expressionType, ExpressionVariables expressionVariables, String shortDesc, Task task, OperationResult result) throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException, CommunicationException, ConfigurationException, SecurityViolationException { diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/GeneralNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/GeneralNotifier.java index 05cfb87652b..d289a8209b4 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/GeneralNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/GeneralNotifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2019 Evolveum and contributors + * Copyright (c) 2020 Evolveum and contributors * * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. @@ -7,404 +7,24 @@ package com.evolveum.midpoint.notifications.impl.notifiers; -import com.evolveum.midpoint.notifications.impl.formatters.ValueFormatter; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.repo.common.expression.ExpressionVariables; -import com.evolveum.midpoint.model.api.ProgressInformation; -import com.evolveum.midpoint.notifications.api.NotificationManager; import com.evolveum.midpoint.notifications.api.events.Event; -import com.evolveum.midpoint.notifications.api.events.ModelEvent; -import com.evolveum.midpoint.notifications.api.events.SimpleObjectRef; -import com.evolveum.midpoint.notifications.api.transports.Message; -import com.evolveum.midpoint.notifications.api.transports.Transport; -import com.evolveum.midpoint.notifications.impl.NotificationFunctionsImpl; -import com.evolveum.midpoint.notifications.impl.formatters.TextFormatter; -import com.evolveum.midpoint.notifications.impl.handlers.AggregatedEventHandler; -import com.evolveum.midpoint.notifications.impl.handlers.BaseHandler; -import com.evolveum.midpoint.prism.PrismValue; -import com.evolveum.midpoint.prism.delta.ItemDelta; -import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.prism.polystring.PolyString; -import com.evolveum.midpoint.schema.constants.ExpressionConstants; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import org.apache.cxf.common.util.StringUtils; -import org.jetbrains.annotations.NotNull; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import java.util.ArrayList; -import java.util.List; +import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralNotifierType; -import static com.evolveum.midpoint.model.api.ProgressInformation.ActivityType.NOTIFICATIONS; -import static com.evolveum.midpoint.model.api.ProgressInformation.StateType.ENTERING; +import org.springframework.stereotype.Component; /** * */ @Component -public class GeneralNotifier extends BaseHandler { - - private static final Trace DEFAULT_LOGGER = TraceManager.getTrace(GeneralNotifier.class); - - @Autowired protected NotificationManager notificationManager; - @Autowired protected NotificationFunctionsImpl functions; - @Autowired protected TextFormatter textFormatter; - @Autowired protected ValueFormatter valueFormatter; - @Autowired protected AggregatedEventHandler aggregatedEventHandler; - - @PostConstruct - public void init() { - register(GeneralNotifierType.class); - } +public class GeneralNotifier extends AbstractGeneralNotifier { @Override - public boolean processEvent(Event event, EventHandlerType eventHandlerType, NotificationManager notificationManager, - Task task, OperationResult parentResult) throws SchemaException { - - OperationResult result = parentResult.createMinorSubresult(GeneralNotifier.class.getName() + ".processEvent"); - - logStart(getLogger(), event, eventHandlerType); - - boolean applies = aggregatedEventHandler.processEvent(event, eventHandlerType, notificationManager, task, result); - - if (applies) { - - GeneralNotifierType generalNotifierType = (GeneralNotifierType) eventHandlerType; - - if (!quickCheckApplicability(event, generalNotifierType, result)) { - - // nothing to do -- an appropriate message has to be logged in quickCheckApplicability method - - } else { - - if (!checkApplicability(event, generalNotifierType, result)) { - // nothing to do -- an appropriate message has to be logged in checkApplicability method - } else if (generalNotifierType.getTransport().isEmpty()) { - getLogger().warn("No transports for this notifier, exiting without sending any notifications."); - } else { - - ExpressionVariables variables = getDefaultVariables(event, result); - - if (event instanceof ModelEvent) { - ((ModelEvent) event).getModelContext().reportProgress(new ProgressInformation(NOTIFICATIONS, ENTERING)); - } - - try { - for (String transportName : generalNotifierType.getTransport()) { - - variables.put(ExpressionConstants.VAR_TRANSPORT_NAME, transportName, String.class); - Transport transport = notificationManager.getTransport(transportName); - - List recipientsAddresses = getRecipientsAddresses(event, generalNotifierType, variables, - getDefaultRecipient(event, generalNotifierType, result), transportName, transport, task, result); - - if (!recipientsAddresses.isEmpty()) { - - String body; - ExpressionType bodyExpression = generalNotifierType.getBodyExpression(); - if (bodyExpression != null) { - body = getBodyFromExpression(event, bodyExpression, variables, task, result); - } else { - body = getBody(event, generalNotifierType, transportName, task, result); - } - if (body == null) { - getLogger().debug("Skipping notification as null body was provided for transport={}", transportName); - continue; - } - - String subject = getSubjectFromExpression(event, generalNotifierType, variables, task, result); - String from = getFromFromExpression(event, generalNotifierType, variables, task, result); - String contentType = getContentTypeFromExpression(event, generalNotifierType, variables, task, result); - List attachments = getAttachmentsFromExpression(event, generalNotifierType, variables, task, result); - - if (subject == null) { - subject = generalNotifierType.getSubjectPrefix() != null ? generalNotifierType.getSubjectPrefix() : ""; - subject += getSubject(event, generalNotifierType, transportName, task, result); - } - - if (attachments == null) { - attachments = generalNotifierType.getAttachment(); - if (attachments == null) { - attachments = getAttachment(event, generalNotifierType, transportName, task, result); - } - } else if (generalNotifierType.getAttachment() != null) { - attachments.addAll(generalNotifierType.getAttachment()); - } - - Message message = new Message(); - message.setBody(body); - if (contentType != null) { - message.setContentType(contentType); - } else if (generalNotifierType.getContentType() != null) { - message.setContentType(generalNotifierType.getContentType()); - } else if (getContentType() != null) { - message.setContentType(getContentType()); - } - message.setSubject(subject); - - if (from != null) { - message.setFrom(from); - } - message.setTo(recipientsAddresses); - message.setCc(getCcBccAddresses(generalNotifierType.getCcExpression(), variables, "notification cc-expression", task, result)); - message.setBcc(getCcBccAddresses(generalNotifierType.getBccExpression(), variables, "notification bcc-expression", task, result)); - - if (attachments != null) { - message.setAttachments(attachments); - } - - getLogger().trace("Sending notification via transport {}:\n{}", transportName, message); - transport.send(message, transportName, event, task, result); - } else { - getLogger().info("No recipients addresses for transport " + transportName + ", message corresponding to event " + event.getId() + " will not be send."); - } - } - } finally { - if (event instanceof ModelEvent) { - ((ModelEvent) event).getModelContext().reportProgress( - new ProgressInformation(NOTIFICATIONS, result)); - } - } - } - } - } - logEnd(getLogger(), event, eventHandlerType, applies); - result.computeStatusIfUnknown(); - return true; // not-applicable notifiers do not stop processing of other notifiers - } - - protected String getContentType() { - return null; - } - - protected boolean quickCheckApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - return true; - } - - protected boolean checkApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - return true; - } - - protected String getSubject(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { - return null; + public Class getEventType() { + return Event.class; } - protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) throws SchemaException { - return null; - } - - @SuppressWarnings("WeakerAccess") // open for future extension - protected List getAttachment(Event event, GeneralNotifierType generalNotifierType, - String transportName, Task task, OperationResult result) { - return null; - } - - protected UserType getDefaultRecipient(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - ObjectType objectType = functions.getObjectType(event.getRequestee(), true, result); - if (objectType instanceof UserType) { - return (UserType) objectType; - } else { - return null; - } - } - - protected Trace getLogger() { - return DEFAULT_LOGGER; // in case a subclass does not provide its own logger - } - - protected List getRecipientsAddresses(Event event, GeneralNotifierType generalNotifierType, ExpressionVariables variables, - UserType defaultRecipient, String transportName, Transport transport, Task task, OperationResult result) { - List addresses = new ArrayList<>(); - if (!generalNotifierType.getRecipientExpression().isEmpty()) { - for (ExpressionType expressionType : generalNotifierType.getRecipientExpression()) { - List r = evaluateExpressionChecked(expressionType, variables, "notification recipient", task, result); - if (r != null) { - addresses.addAll(r); - } - } - if (addresses.isEmpty()) { - getLogger().info("Notification for " + event + " will not be sent, because there are no known recipients."); - } - } else if (defaultRecipient == null) { - getLogger().info("Unknown default recipient, notification will not be sent."); - } else { - String address = transport.getDefaultRecipientAddress(defaultRecipient); - if (StringUtils.isEmpty(address)) { - getLogger().info("Notification to " + defaultRecipient.getName() + " will not be sent, because the user has no address (mail, phone number, etc) for transport '" + transportName + "' set."); - } else { - addresses.add(address); - } - } - return addresses; - } - - @NotNull - protected List getCcBccAddresses(List expressions, ExpressionVariables variables, - String shortDesc, Task task, OperationResult result) { - List addresses = new ArrayList<>(); - for (ExpressionType expressionType : expressions) { - List r = evaluateExpressionChecked(expressionType, variables, shortDesc, task, result); - if (r != null) { - addresses.addAll(r); - } - } - return addresses; - } - - protected String getSubjectFromExpression(Event event, GeneralNotifierType generalNotifierType, ExpressionVariables variables, - Task task, OperationResult result) { - return getStringFromExpression(event, variables, task, result, generalNotifierType.getSubjectExpression(), "subject", false); - } - - protected String getFromFromExpression(Event event, GeneralNotifierType generalNotifierType, ExpressionVariables variables, - Task task, OperationResult result) { - return getStringFromExpression(event, variables, task, result, generalNotifierType.getFromExpression(), "from", true); - } - - protected String getContentTypeFromExpression(Event event, GeneralNotifierType generalNotifierType, ExpressionVariables variables, - Task task, OperationResult result) { - return getStringFromExpression(event, variables, task, result, generalNotifierType.getContentTypeExpression(), "contentType", true); - } - - protected String getStringFromExpression(Event event, ExpressionVariables variables, - Task task, OperationResult result, ExpressionType expression, String expressionTypeName, boolean canBeNull) { - if (expression != null) { - List contentTypeList = evaluateExpressionChecked(expression, variables, expressionTypeName + " expression", - task, result); - if (contentTypeList == null || contentTypeList.isEmpty()) { - getLogger().info(expressionTypeName + " expression for event " + event.getId() + " returned nothing."); - return canBeNull ? null : ""; - } - if (contentTypeList.size() > 1) { - getLogger().warn(expressionTypeName + " expression for event " + event.getId() + " returned more than 1 item."); - } - return contentTypeList.get(0); - } else { - return null; - } - } - - @NotNull - private String getBodyFromExpression(Event event, @NotNull ExpressionType bodyExpression, ExpressionVariables variables, - Task task, OperationResult result) { - List bodyList = evaluateExpressionChecked(bodyExpression, variables, - "body expression", task, result); - if (bodyList == null || bodyList.isEmpty()) { - getLogger().warn("Body expression for event " + event.getId() + " returned nothing."); - return ""; - } - StringBuilder body = new StringBuilder(); - for (String s : bodyList) { - body.append(s); - } - return body.toString(); - } - - private List getAttachmentsFromExpression(Event event, GeneralNotifierType generalNotifierType, ExpressionVariables variables, - Task task, OperationResult result) { - if (generalNotifierType.getAttachmentExpression() != null) { - List attachment = evaluateNotificationMessageAttachmentTypeExpressionChecked(generalNotifierType.getAttachmentExpression(), variables, "contentType expression", - task, result); - if (attachment == null) { - getLogger().info("attachment expression for event " + event.getId() + " returned nothing."); - return null; - } - return attachment; - } else { - return null; - } - } - - // TODO implement more efficiently - // precondition: delta is MODIFY delta - boolean deltaContainsOtherPathsThan(ObjectDelta delta, List paths) { - - for (ItemDelta itemDelta : delta.getModifications()) { - if (!NotificationFunctionsImpl.isAmongHiddenPaths(itemDelta.getPath(), paths)) { - return true; - } - } - return false; - } - - boolean isWatchAuxiliaryAttributes(GeneralNotifierType generalNotifierType) { - return Boolean.TRUE.equals((generalNotifierType).isWatchAuxiliaryAttributes()); - } - - protected void appendModifications(StringBuilder body, ObjectDelta delta, List hiddenPaths, Boolean showValuesBoolean) { - - boolean showValues = !Boolean.FALSE.equals(showValuesBoolean); - for (ItemDelta itemDelta : delta.getModifications()) { - if (NotificationFunctionsImpl.isAmongHiddenPaths(itemDelta.getPath(), hiddenPaths)) { - continue; - } - body.append(" - "); - body.append(formatPath(itemDelta)); - - if (showValues) { - body.append(":\n"); - - if (itemDelta.isAdd()) { - for (PrismValue prismValue : itemDelta.getValuesToAdd()) { - body.append(" --- ADD: "); - body.append(prismValue.debugDump(2)); - body.append("\n"); - } - } - if (itemDelta.isDelete()) { - for (PrismValue prismValue : itemDelta.getValuesToDelete()) { - body.append(" --- DELETE: "); - body.append(prismValue.debugDump(2)); - body.append("\n"); - } - } - if (itemDelta.isReplace()) { - for (PrismValue prismValue : itemDelta.getValuesToReplace()) { - body.append(" --- REPLACE: "); - body.append(prismValue.debugDump(2)); - body.append("\n"); - } - } - } else { - body.append("\n"); - } - } - } - - private String formatPath(ItemDelta itemDelta) { - if (itemDelta.getDefinition() != null && itemDelta.getDefinition().getDisplayName() != null) { - return itemDelta.getDefinition().getDisplayName(); - } - StringBuilder sb = new StringBuilder(); - for (Object segment : itemDelta.getPath().getSegments()) { - if (ItemPath.isName(segment)) { - if (sb.length() > 0) { - sb.append("/"); - } - sb.append(ItemPath.toName(segment).getLocalPart()); - } - } - return sb.toString(); - } - - public String formatRequester(Event event, OperationResult result) { - SimpleObjectRef requesterRef = event.getRequester(); - if (requesterRef == null) { - return "(unknown or none)"; - } - ObjectType requester = requesterRef.resolveObjectType(result, false); - String name = PolyString.getOrig(requester.getName()); - if (requester instanceof UserType) { - return name + " (" + PolyString.getOrig(((UserType) requester).getFullName()) + ")"; - } else { - return name; - } + @Override + public Class getEventHandlerConfigurationType() { + return GeneralNotifierType.class; } - } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/PasswordResetNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/PasswordResetNotifier.java index 63767a80d69..91e4b7522ff 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/PasswordResetNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/PasswordResetNotifier.java @@ -21,19 +21,20 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; @Component -public class PasswordResetNotifier extends ConfirmationNotifier { +public class PasswordResetNotifier extends ConfirmationNotifier { private static final Trace LOGGER = TraceManager.getTrace(ConfirmationNotifier.class); @Override - public void init() { - register(PasswordResetNotifierType.class); + public Class getEventHandlerConfigurationType() { + return PasswordResetNotifierType.class; } @Override - protected boolean quickCheckApplicability(Event event, GeneralNotifierType generalNotifierType, + protected boolean quickCheckApplicability(ModelEvent event, PasswordResetNotifierType configuration, OperationResult result) { - if (!(super.quickCheckApplicability(event, generalNotifierType, result)) || !((ModelEvent) event).hasFocusOfType(UserType.class)) { + // TODO generalize to FocusType + if (!event.hasFocusOfType(UserType.class)) { LOGGER.trace( "PasswordResetNotifier is not applicable for this kind of event, continuing in the handler chain; event class = " + event.getClass()); @@ -44,19 +45,15 @@ protected boolean quickCheckApplicability(Event event, GeneralNotifierType gener } @Override - protected boolean checkApplicability(Event event, GeneralNotifierType generalNotifierType, + protected boolean checkApplicability(ModelEvent event, PasswordResetNotifierType configuration, OperationResult result) { if (!event.isSuccess()) { LOGGER.trace("Operation was not successful, exiting."); return false; - } - - ModelEvent modelEvent = (ModelEvent) event; - if (modelEvent.getFocusDeltas().isEmpty()) { + } else if (event.getFocusDeltas().isEmpty()) { LOGGER.trace("No user deltas in event, exiting."); return false; - } - if (SchemaConstants.CHANNEL_GUI_RESET_PASSWORD_URI.equals(modelEvent.getChannel())) { + } else if (SchemaConstants.CHANNEL_GUI_RESET_PASSWORD_URI.equals(event.getChannel())) { LOGGER.trace("Found change from reset password channel."); return true; } else { @@ -66,18 +63,17 @@ protected boolean checkApplicability(Event event, GeneralNotifierType generalNot } @Override - protected String getSubject(Event event, GeneralNotifierType generalNotifierType, String transport, + protected String getSubject(ModelEvent event, PasswordResetNotifierType configuration, String transport, Task task, OperationResult result) { return "Password reset"; } @Override - protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { - + protected String getBody(ModelEvent event, PasswordResetNotifierType generalNotifierType, String transport, Task task, + OperationResult result) { UserType userType = getUser(event); - - return "Did you request password reset? If yes, click on the link bellow \n\n" + createConfirmationLink(userType, generalNotifierType, result); - + return "Did you request password reset? If yes, click on the link bellow \n\n" + + createConfirmationLink(userType, generalNotifierType, result); } @Override diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/RegistrationConfirmationNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/RegistrationConfirmationNotifier.java index ca42dbfeb70..30317740167 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/RegistrationConfirmationNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/RegistrationConfirmationNotifier.java @@ -10,7 +10,6 @@ import org.springframework.stereotype.Component; -import com.evolveum.midpoint.notifications.api.events.Event; import com.evolveum.midpoint.notifications.api.events.ModelEvent; import com.evolveum.midpoint.prism.crypto.EncryptionException; import com.evolveum.midpoint.schema.constants.SchemaConstants; @@ -18,25 +17,24 @@ import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.RegistrationConfirmationNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; @Component -public class RegistrationConfirmationNotifier extends ConfirmationNotifier { +public class RegistrationConfirmationNotifier extends ConfirmationNotifier { private static final Trace LOGGER = TraceManager.getTrace(ConfirmationNotifier.class); @Override - public void init() { - register(RegistrationConfirmationNotifierType.class); + public Class getEventHandlerConfigurationType() { + return RegistrationConfirmationNotifierType.class; } @Override - protected boolean quickCheckApplicability(Event event, GeneralNotifierType generalNotifierType, + protected boolean quickCheckApplicability(ModelEvent event, RegistrationConfirmationNotifierType configuration, OperationResult result) { - if (!(super.quickCheckApplicability(event, generalNotifierType, result)) - || !((ModelEvent) event).hasFocusOfType(UserType.class)) { + // TODO generalize to FocusType + if (!event.hasFocusOfType(UserType.class)) { LOGGER.trace( "RegistrationConfirmationNotifier is not applicable for this kind of event, continuing in the handler chain; event class = " + event.getClass()); @@ -47,19 +45,15 @@ protected boolean quickCheckApplicability(Event event, GeneralNotifierType gener } @Override - protected boolean checkApplicability(Event event, GeneralNotifierType generalNotifierType, + protected boolean checkApplicability(ModelEvent event, RegistrationConfirmationNotifierType configuration, OperationResult result) { if (!event.isSuccess()) { LOGGER.trace("Operation was not successful, exiting."); return false; - } - - ModelEvent modelEvent = (ModelEvent) event; - if (modelEvent.getFocusDeltas().isEmpty()) { + } else if (event.getFocusDeltas().isEmpty()) { LOGGER.trace("No user deltas in event, exiting."); return false; - } - if (SchemaConstants.CHANNEL_GUI_SELF_REGISTRATION_URI.equals(modelEvent.getChannel())) { + } else if (SchemaConstants.CHANNEL_GUI_SELF_REGISTRATION_URI.equals(event.getChannel())) { LOGGER.trace("Found change from registration channel."); return true; } else { @@ -69,13 +63,14 @@ protected boolean checkApplicability(Event event, GeneralNotifierType generalNot } @Override - protected String getSubject(Event event, GeneralNotifierType generalNotifierType, String transport, + protected String getSubject(ModelEvent event, RegistrationConfirmationNotifierType configuration, String transport, Task task, OperationResult result) { return "Registration confirmation"; } @Override - protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { + protected String getBody(ModelEvent event, RegistrationConfirmationNotifierType configuration, String transport, + Task task, OperationResult result) { UserType userType = getUser(event); @@ -90,7 +85,7 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S messageBuilder.append(userType.getGivenName()).append(",\n") .append("your account was successfully created. To activate your account click on the following confiramtion link. ") .append("\n") - .append(createConfirmationLink(userType, generalNotifierType, result)) + .append(createConfirmationLink(userType, configuration, result)) .append("\n\n") .append("After your account is activated, use following credentials to log in: \n") .append("username: ") @@ -104,6 +99,5 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S @Override public String getConfirmationLink(UserType userType) { return getMidpointFunctions().createRegistrationConfirmationLink(userType); - } } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleCampaignNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleCampaignNotifier.java index 90feff59bb9..b430b2a64dd 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleCampaignNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleCampaignNotifier.java @@ -7,76 +7,71 @@ package com.evolveum.midpoint.notifications.impl.notifiers; +import java.util.Date; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.notifications.api.events.CertCampaignEvent; -import com.evolveum.midpoint.notifications.api.events.Event; import com.evolveum.midpoint.notifications.impl.helpers.CertHelper; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SimpleCampaignNotifierType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import java.util.Date; /** * Various campaign-level notifications. - * - * @author mederly */ @Component -public class SimpleCampaignNotifier extends GeneralNotifier { +public class SimpleCampaignNotifier extends AbstractGeneralNotifier { private static final Trace LOGGER = TraceManager.getTrace(SimpleCampaignNotifier.class); @Autowired private CertHelper certHelper; - @PostConstruct - public void init() { - register(SimpleCampaignNotifierType.class); + @Override + public Class getEventType() { + return CertCampaignEvent.class; } @Override - protected boolean quickCheckApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - if (!(event instanceof CertCampaignEvent)) { - LOGGER.trace("SimpleCampaignNotifier is not applicable for this kind of event, continuing in the handler chain; event class = " + event.getClass()); - return false; - } + public Class getEventHandlerConfigurationType() { + return SimpleCampaignNotifierType.class; + } + + @Override + protected boolean quickCheckApplicability(CertCampaignEvent event, SimpleCampaignNotifierType configuration, OperationResult result) { // general modifications are not supported return event.isAdd() || event.isDelete(); } @Override - protected String getSubject(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { - CertCampaignEvent campaignEvent = (CertCampaignEvent) event; + protected String getSubject(CertCampaignEvent event, SimpleCampaignNotifierType configuration, String transport, Task task, OperationResult result) { String change; - if (campaignEvent.isAdd()) { + if (event.isAdd()) { change = "started"; - } else if (campaignEvent.isDelete()) { + } else if (event.isDelete()) { change = "closed"; } else { throw new IllegalStateException("Unexpected campaign event type: neither ADD nor DELETE"); } - return "Campaign " + campaignEvent.getCampaignName() + " " + change; + return "Campaign " + event.getCampaignName() + " " + change; } @Override - protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { + protected String getBody(CertCampaignEvent event, SimpleCampaignNotifierType configuration, String transport, Task task, OperationResult result) { StringBuilder body = new StringBuilder(); - CertCampaignEvent campaignEvent = (CertCampaignEvent) event; - AccessCertificationCampaignType campaign = campaignEvent.getCampaign(); + AccessCertificationCampaignType campaign = event.getCampaign(); body.append("Campaign "); - body.append(certHelper.getCampaignNameAndOid(campaignEvent)); + body.append(certHelper.getCampaignNameAndOid(event)); body.append(" was "); - if (campaignEvent.isAdd()) { + if (event.isAdd()) { body.append("STARTED"); - } else if (campaignEvent.isDelete()) { + } else if (event.isDelete()) { body.append("CLOSED"); } else { throw new IllegalStateException("Unexpected campaign event type: neither ADD nor DELETE"); @@ -85,9 +80,9 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S body.append("Time: ").append(new Date()); // the event is generated in the real time body.append("\nRequester: ").append(formatRequester(event, result)); - body.append("\nOperation status: ").append(certHelper.formatStatus(campaignEvent)); + body.append("\nOperation status: ").append(certHelper.formatStatus(event)); - body.append("\n\nCurrent state: ").append(certHelper.formatState(campaignEvent)); + body.append("\n\nCurrent state: ").append(certHelper.formatState(event)); body.append("\n\n"); certHelper.appendStatistics(body, campaign, task, result); @@ -101,5 +96,4 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S protected Trace getLogger() { return LOGGER; } - } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleCampaignStageNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleCampaignStageNotifier.java index 6074fb21c96..c346332455f 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleCampaignStageNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleCampaignStageNotifier.java @@ -7,8 +7,13 @@ package com.evolveum.midpoint.notifications.impl.notifiers; +import java.util.Date; + +import org.apache.commons.lang.time.DurationFormatUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.notifications.api.events.CertCampaignStageEvent; -import com.evolveum.midpoint.notifications.api.events.Event; import com.evolveum.midpoint.notifications.impl.helpers.CertHelper; import com.evolveum.midpoint.prism.xml.XmlTypeConverter; import com.evolveum.midpoint.schema.result.OperationResult; @@ -18,86 +23,71 @@ import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationStageType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SimpleCampaignStageNotifierType; -import org.apache.commons.lang.time.DurationFormatUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import java.util.Date; /** * Various stage-level notifications. - * - * @author mederly */ @Component -public class SimpleCampaignStageNotifier extends GeneralNotifier { +public class SimpleCampaignStageNotifier extends AbstractGeneralNotifier { private static final Trace LOGGER = TraceManager.getTrace(SimpleCampaignStageNotifier.class); - @Autowired - private CertHelper certHelper; + @Autowired private CertHelper certHelper; - @PostConstruct - public void init() { - register(SimpleCampaignStageNotifierType.class); + @Override + public Class getEventType() { + return CertCampaignStageEvent.class; } @Override - protected boolean quickCheckApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - if (!(event instanceof CertCampaignStageEvent)) { - LOGGER.trace("SimpleCampaignStageNotifier is not applicable for this kind of event, continuing in the handler chain; event class = " + event.getClass()); - return false; - } - return true; + public Class getEventHandlerConfigurationType() { + return SimpleCampaignStageNotifierType.class; } @Override - protected String getSubject(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { - CertCampaignStageEvent csEvent = (CertCampaignStageEvent) event; + protected String getSubject(CertCampaignStageEvent event, SimpleCampaignStageNotifierType configuration, String transport, Task task, OperationResult result) { String change; - if (csEvent.isAdd()) { + if (event.isAdd()) { change = "started"; - } else if (csEvent.isDelete()) { + } else if (event.isDelete()) { change = "closed"; - } else if (csEvent.isModify()) { + } else if (event.isModify()) { change = "about to be closed"; } else { throw new IllegalStateException("Unexpected campaign event type: neither ADD nor MODIFY nor DELETE"); } - return "Campaign " + csEvent.getCampaignName() - + " " + certHelper.getStageShortName(csEvent.getCampaign()) + return "Campaign " + event.getCampaignName() + + " " + certHelper.getStageShortName(event.getCampaign()) + " " + change; } @Override - protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { + protected String getBody(CertCampaignStageEvent event, SimpleCampaignStageNotifierType configuration, String transport, + Task task, OperationResult result) { StringBuilder body = new StringBuilder(); - CertCampaignStageEvent csEvent = (CertCampaignStageEvent) event; - AccessCertificationCampaignType campaign = csEvent.getCampaign(); + AccessCertificationCampaignType campaign = event.getCampaign(); body.append("A certification campaign stage "); - if (csEvent.isAdd()) { + if (event.isAdd()) { body.append("has been started"); - } else if (csEvent.isDelete()) { + } else if (event.isDelete()) { body.append("has been closed"); - } else if (csEvent.isModify()) { + } else if (event.isModify()) { body.append("is about to be closed"); } body.append("."); body.append("\n\nCampaign: "); - body.append(certHelper.getCampaignNameAndOid(csEvent)); + body.append(certHelper.getCampaignNameAndOid(event)); body.append("\nState: "); - body.append(certHelper.formatState(csEvent)); + body.append(certHelper.formatState(event)); body.append("\n\nTime: ").append(new Date()); // the event is generated in the real time AccessCertificationStageType stage = CertCampaignTypeUtil.getCurrentStage(campaign); if (stage != null) { body.append("\n\nStage start time: ").append(XmlTypeConverter.toDate(stage.getStartTimestamp())); body.append("\nStage deadline time: ").append(XmlTypeConverter.toDate(stage.getDeadline())); - if (csEvent.isModify() && stage.getDeadline() != null) { + if (event.isModify() && stage.getDeadline() != null) { long delta = XmlTypeConverter.toMillis(stage.getDeadline()) - System.currentTimeMillis(); if (delta > 0) { body.append("\n\nStage ends in "); @@ -110,9 +100,9 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S } } body.append("\n"); - if (csEvent.isAdd() || csEvent.isDelete()) { + if (event.isAdd() || event.isDelete()) { body.append("\nRequester: ").append(formatRequester(event, result)); - body.append("\nOperation status: ").append(certHelper.formatStatus(csEvent)); + body.append("\nOperation status: ").append(certHelper.formatStatus(event)); body.append("\n"); } @@ -129,5 +119,4 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S protected Trace getLogger() { return LOGGER; } - } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleFocalObjectNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleFocalObjectNotifier.java index 862232e079c..0e612b6504d 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleFocalObjectNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleFocalObjectNotifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Evolveum and contributors + * Copyright (c) 2020 Evolveum and contributors * * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. @@ -7,169 +7,30 @@ package com.evolveum.midpoint.notifications.impl.notifiers; -import com.evolveum.midpoint.model.api.context.ModelContext; -import com.evolveum.midpoint.model.api.context.ModelElementContext; -import com.evolveum.midpoint.notifications.api.events.Event; -import com.evolveum.midpoint.notifications.api.events.ModelEvent; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.prism.delta.ObjectDeltaCollectionsUtil; -import com.evolveum.midpoint.prism.polystring.PolyString; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; - -import org.jetbrains.annotations.Nullable; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; -import java.util.Date; -import java.util.List; - -import static com.evolveum.midpoint.util.MiscUtil.emptyIfNull; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SimpleFocalObjectNotifierType; -/** - * @author mederly - */ @Component -public class SimpleFocalObjectNotifier extends GeneralNotifier { +public class SimpleFocalObjectNotifier extends AbstractFocalObjectNotifier { private static final Trace LOGGER = TraceManager.getTrace(SimpleFocalObjectNotifier.class); - @PostConstruct - public void init() { - register(SimpleFocalObjectNotifierType.class); - } - @Override - protected boolean quickCheckApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - if (!(event instanceof ModelEvent)) { - LOGGER.trace("{} is not applicable for this kind of event, continuing in the handler chain; event class = {}", getClass().getSimpleName(), event.getClass()); - return false; - } - ModelEvent modelEvent = (ModelEvent) event; - if (modelEvent.getFocusContext() == null || !modelEvent.getFocusContext().isOfType(FocusType.class)) { - LOGGER.trace("{} is not applicable to non-focus related model operations, continuing in the handler chain", getClass().getSimpleName()); - return false; - } - return true; + public Class getEventHandlerConfigurationType() { + return SimpleFocalObjectNotifierType.class; } @Override - protected boolean checkApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - List> deltas = ((ModelEvent) event).getFocusDeltas(); - if (deltas.isEmpty()) { - LOGGER.trace("No deltas found, skipping the notification"); - return false; - } - - if (isWatchAuxiliaryAttributes(generalNotifierType)) { - return true; - } - - for (ObjectDelta delta : deltas) { - if (!delta.isModify() || deltaContainsOtherPathsThan(delta, functions.getAuxiliaryPaths())) { - return true; - } - } - - LOGGER.trace("No deltas for non-auxiliary attributes found, skipping the notification"); - return false; - } - - @Override - protected String getSubject(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { - - final ModelEvent modelEvent = (ModelEvent) event; - String typeName = modelEvent.getFocusTypeName(); - - if (event.isAdd()) { - return typeName + " creation notification"; - } else if (event.isModify()) { - return typeName + " modification notification"; - } else if (event.isDelete()) { - return typeName + " deletion notification"; - } else { - return "(unknown " + typeName.toLowerCase() + " operation)"; - } - } - - @Override - protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) throws SchemaException { - - ModelEvent modelEvent = (ModelEvent) event; - - String typeName = modelEvent.getFocusTypeName(); - String typeNameLower = typeName.toLowerCase(); - - boolean techInfo = Boolean.TRUE.equals(generalNotifierType.isShowTechnicalInformation()); - - //noinspection unchecked - ModelContext modelContext = (ModelContext) modelEvent.getModelContext(); - ModelElementContext focusContext = modelContext.getFocusContext(); - PrismObject focusObject = focusContext.getObjectNew() != null ? focusContext.getObjectNew() : focusContext.getObjectOld(); - FocusType focus = focusObject.asObjectable(); - String oid = focusContext.getOid(); - - String fullName = emptyIfNull(getFullName(focus)); - - ObjectDelta delta = ObjectDeltaCollectionsUtil.summarize(modelEvent.getFocusDeltas()); - - StringBuilder body = new StringBuilder(); - - String status = modelEvent.getStatusAsText(); - String attemptedTo = event.isSuccess() ? "" : "(attempted to be) "; - - body.append("Notification about ").append(typeNameLower).append("-related operation (status: ").append(status).append(")\n\n"); - body.append(typeName).append(": ").append(fullName).append(" (").append(focus.getName()).append(", oid ").append(oid).append(")\n"); - body.append("Notification created on: ").append(new Date()).append("\n\n"); - - final boolean watchAuxiliaryAttributes = isWatchAuxiliaryAttributes(generalNotifierType); - if (delta.isAdd()) { - body.append("The ").append(typeNameLower).append(" record was ").append(attemptedTo).append("created with the following data:\n"); - body.append(modelEvent.getContentAsFormattedList(false, watchAuxiliaryAttributes)); - } else if (delta.isModify()) { - body.append("The ").append(typeNameLower).append(" record was ").append(attemptedTo).append("modified. Modified attributes are:\n"); - body.append(modelEvent.getContentAsFormattedList(false, watchAuxiliaryAttributes)); - } else if (delta.isDelete()) { - body.append("The ").append(typeNameLower).append(" record was ").append(attemptedTo).append("removed.\n"); - } - body.append("\n"); - - if (!event.isSuccess()) { - body.append("More information about the status of the request was displayed and/or is present in log files.\n\n"); - } - - functions.addRequesterAndChannelInformation(body, event, result); - - if (techInfo) { - body.append("----------------------------------------\n"); - body.append("Technical information:\n\n"); - body.append(modelContext.debugDump(2)); - } - - return body.toString(); - } - - @Nullable - private String getFullName(FocusType focus) { - String fullName; - if (focus instanceof UserType) { - fullName = PolyString.getOrig(((UserType) focus).getFullName()); - } else if (focus instanceof AbstractRoleType) { - fullName = PolyString.getOrig(((AbstractRoleType) focus).getDisplayName()); - } else { - fullName = ""; // TODO (currently it's not possible to get here) - } - return fullName; + Class getFocusClass() { + return FocusType.class; } @Override protected Trace getLogger() { return LOGGER; } - } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimplePolicyRuleNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimplePolicyRuleNotifier.java index 1b04abfe2eb..396738d895c 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimplePolicyRuleNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimplePolicyRuleNotifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2017 Evolveum and contributors + * Copyright (c) 2020 Evolveum and contributors * * This work is dual-licensed under the Apache License 2.0 * and European Union Public License. See LICENSE file for details. @@ -7,67 +7,18 @@ package com.evolveum.midpoint.notifications.impl.notifiers; -import com.evolveum.midpoint.notifications.api.events.Event; -import com.evolveum.midpoint.notifications.api.events.PolicyRuleEvent; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SimplePolicyRuleNotifierType; -import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; +import org.springframework.stereotype.Component; /** - * @author mederly + * */ @Component -public class SimplePolicyRuleNotifier extends GeneralNotifier { - - private static final Trace LOGGER = TraceManager.getTrace(SimplePolicyRuleNotifier.class); - - @PostConstruct - public void init() { - register(SimplePolicyRuleNotifierType.class); - } +public class SimplePolicyRuleNotifier extends AbstractPolicyRuleNotifier { @Override - protected boolean quickCheckApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - if (!(event instanceof PolicyRuleEvent)) { - LOGGER.trace("{} is not applicable for this kind of event, continuing in the handler chain; event class = {}", getClass().getSimpleName(), event.getClass()); - return false; - } - return true; + public Class getEventHandlerConfigurationType() { + return SimplePolicyRuleNotifierType.class; } - - @Override - protected boolean checkApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - return true; - } - - @Override - protected String getSubject(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { - PolicyRuleEvent ruleEvent = (PolicyRuleEvent) event; - return "Policy rule '" + ruleEvent.getRuleName() + "' triggering notification"; - } - - @Override - protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, Task opTask, OperationResult opResult) throws SchemaException { - PolicyRuleEvent ruleEvent = (PolicyRuleEvent) event; - - StringBuilder body = new StringBuilder(); - - body.append("Notification about policy rule-related event.\n\n"); - // TODO TODO TODO - body.append(ruleEvent.getPolicyRule().debugDump()); - return body.toString(); - } - - @Override - protected Trace getLogger() { - return LOGGER; - } - } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleReportNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleReportNotifier.java index c5b7ca4b6b9..f5923f80c2a 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleReportNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleReportNotifier.java @@ -7,55 +7,33 @@ package com.evolveum.midpoint.notifications.impl.notifiers; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.model.api.ModelService; -import com.evolveum.midpoint.notifications.api.events.Event; import com.evolveum.midpoint.notifications.api.events.TaskEvent; import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismProperty; -import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.report.api.ReportConstants; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.task.api.TaskCategory; -import com.evolveum.midpoint.util.Producer; -import com.evolveum.midpoint.util.exception.CommunicationException; -import com.evolveum.midpoint.util.exception.ConfigurationException; -import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SecurityViolationException; -import com.evolveum.midpoint.util.logging.LoggingUtils; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ExportType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralNotifierType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ReportOutputType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SimpleReportNotifierType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -import org.apache.commons.lang.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; /** * @author mederly * @author skublik */ @Component -public class SimpleReportNotifier extends GeneralNotifier { +public class SimpleReportNotifier extends AbstractGeneralNotifier { private static final Trace LOGGER = TraceManager.getTrace(SimpleReportNotifier.class); @@ -63,45 +41,43 @@ public class SimpleReportNotifier extends GeneralNotifier { @Autowired private ModelService modelService; - @PostConstruct - public void init() { - register(SimpleReportNotifierType.class); + @Override + public Class getEventType() { + return TaskEvent.class; } @Override - protected boolean quickCheckApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - if (!(event instanceof TaskEvent) || ((TaskEvent)event).getTask() == null - || ((TaskEvent)event).getTask().getCategory() == null || !((TaskEvent)event).getTask().getHandlerUri().equals(REPORT_HTML_CREATE_TASK_URI)) { - LOGGER.trace("{} is not applicable for this kind of event, continuing in the handler chain; event class = {}", getClass().getSimpleName(), event.getClass()); - return false; - } - return true; + public Class getEventHandlerConfigurationType() { + return SimpleReportNotifierType.class; } @Override - protected boolean checkApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - return true; + protected boolean quickCheckApplicability(TaskEvent event, SimpleReportNotifierType configuration, OperationResult result) { + if (event.getTask().getCategory() == null || !event.getTask().getHandlerUri().equals(REPORT_HTML_CREATE_TASK_URI)) { + LOGGER.trace("{} is not applicable for this kind of event, continuing in the handler chain; event class = {}", + getClass().getSimpleName(), event.getClass()); + return false; + } else { + return true; + } } @Override - protected String getSubject(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { - final TaskEvent taskEvent = (TaskEvent) event; - final String taskName = PolyString.getOrig(taskEvent.getTask().getName()); + protected String getSubject(TaskEvent event, SimpleReportNotifierType configuration, String transport, Task task, OperationResult result) { + final String taskName = PolyString.getOrig(event.getTask().getName()); if (event.isAdd()) { return "Task '" + taskName + "' start notification"; } else if (event.isDelete()) { - return "Task '" + taskName + "' finish notification: " + taskEvent.getOperationResultStatus(); + return "Task '" + taskName + "' finish notification: " + event.getOperationResultStatus(); } else { return "(unknown " + taskName + " operation)"; } } @Override - protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, Task opTask, OperationResult opResult) throws SchemaException { - final TaskEvent taskEvent = (TaskEvent) event; - final Task task = taskEvent.getTask(); - + protected String getBody(TaskEvent event, SimpleReportNotifierType configuration, String transport, Task opTask, OperationResult opResult) throws SchemaException { + Task task = event.getTask(); String outputOid = task.getExtensionPropertyRealValue(ReportConstants.REPORT_OUTPUT_OID_PROPERTY_NAME); @@ -109,26 +85,22 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S throw new IllegalStateException("Unexpected oid of report output, oid is null or empty"); } - PrismObject reportOutput = null; + PrismObject reportOutput; try { - reportOutput = modelService.getObject(ReportOutputType.class, outputOid, null, opTask, opTask.getResult()); + reportOutput = modelService.getObject(ReportOutputType.class, outputOid, null, opTask, opResult); } catch (ObjectNotFoundException | SecurityViolationException | CommunicationException | ConfigurationException | ExpressionEvaluationException e) { getLogger().error("Could't get Report output with oid " + outputOid, e); + throw new SystemException("Couldn't get report output " + outputOid, e); } - if (reportOutput == null) { - throw new IllegalStateException("Unexpected report output, report output is null"); - } - - String body = ""; try { byte[] encoded = Files.readAllBytes(Paths.get(reportOutput.asObjectable().getFilePath())); - body = new String(encoded, Charset.defaultCharset()); + return new String(encoded, Charset.defaultCharset()); } catch (IOException e) { getLogger().error("Couldn't create body from ReportOutput with oid " + outputOid, e); + return ""; } - return body; } @Override @@ -139,5 +111,4 @@ protected Trace getLogger() { protected String getContentType() { return "text/html"; } - } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleResourceObjectNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleResourceObjectNotifier.java index 3e5f09d3b94..9d3856a42a7 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleResourceObjectNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleResourceObjectNotifier.java @@ -7,9 +7,12 @@ package com.evolveum.midpoint.notifications.impl.notifiers; +import java.util.Date; + +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.notifications.api.OperationStatus; import com.evolveum.midpoint.notifications.api.events.ResourceObjectEvent; -import com.evolveum.midpoint.notifications.api.events.Event; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.provisioning.api.ResourceOperationDescription; import com.evolveum.midpoint.schema.result.OperationResult; @@ -18,48 +21,36 @@ import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -import java.util.Date; - /** - * @author mederly + * */ @Component -public class SimpleResourceObjectNotifier extends GeneralNotifier { +public class SimpleResourceObjectNotifier extends AbstractGeneralNotifier { private static final Trace LOGGER = TraceManager.getTrace(SimpleResourceObjectNotifier.class); - @PostConstruct - public void init() { - register(SimpleResourceObjectNotifierType.class); + @Override + public Class getEventType() { + return ResourceObjectEvent.class; } @Override - protected boolean quickCheckApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - if (!(event instanceof ResourceObjectEvent)) { - LOGGER.trace("SimpleResourceObjectNotifier is not applicable for this kind of event, continuing in the handler chain; event class = " + event.getClass()); - return false; - } else { - return true; - } + public Class getEventHandlerConfigurationType() { + return SimpleResourceObjectNotifierType.class; } @Override - protected boolean checkApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { + protected boolean checkApplicability(ResourceObjectEvent event, SimpleResourceObjectNotifierType configuration, OperationResult result) { - ResourceObjectEvent resourceObjectEvent = (ResourceObjectEvent) event; - ObjectDelta delta = resourceObjectEvent.getShadowDelta(); + ObjectDelta delta = event.getShadowDelta(); if (!delta.isModify()) { return true; } boolean otherThanSyncPresent = deltaContainsOtherPathsThan(delta, functions.getSynchronizationPaths()); boolean otherThanAuxPresent = deltaContainsOtherPathsThan(delta, functions.getAuxiliaryPaths()); - boolean watchSync = isWatchSynchronizationAttributes((SimpleResourceObjectNotifierType) generalNotifierType); - boolean watchAux = isWatchAuxiliaryAttributes(generalNotifierType); + boolean watchSync = isWatchSynchronizationAttributes(configuration); + boolean watchAux = isWatchAuxiliaryAttributes(configuration); if ((watchSync || otherThanSyncPresent) && (watchAux || otherThanAuxPresent)) { return true; } @@ -69,19 +60,17 @@ protected boolean checkApplicability(Event event, GeneralNotifierType generalNot return false; } - private boolean isWatchSynchronizationAttributes(SimpleResourceObjectNotifierType generalNotifierType) { - return Boolean.TRUE.equals((generalNotifierType).isWatchSynchronizationAttributes()); + private boolean isWatchSynchronizationAttributes(SimpleResourceObjectNotifierType configuration) { + return Boolean.TRUE.equals((configuration).isWatchSynchronizationAttributes()); } @Override - protected String getSubject(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { - - ResourceObjectEvent resourceObjectEvent = (ResourceObjectEvent) event; - - ResourceOperationDescription rod = resourceObjectEvent.getAccountOperationDescription(); + protected String getSubject(ResourceObjectEvent event, SimpleResourceObjectNotifierType configuration, String transport, Task task, OperationResult result) { + ResourceOperationDescription rod = event.getAccountOperationDescription(); + //noinspection unchecked ObjectDelta delta = (ObjectDelta) rod.getObjectDelta(); - String objectTypeDescription = resourceObjectEvent.isShadowKind(ShadowKindType.ACCOUNT) ? "Account" : "Resource object"; + String objectTypeDescription = event.isShadowKind(ShadowKindType.ACCOUNT) ? "Account" : "Resource object"; if (delta.isAdd()) { return objectTypeDescription + " creation notification"; @@ -95,39 +84,38 @@ protected String getSubject(Event event, GeneralNotifierType generalNotifierType } @Override - protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { + protected String getBody(ResourceObjectEvent event, SimpleResourceObjectNotifierType configuration, String transport, Task task, OperationResult result) { - boolean techInfo = Boolean.TRUE.equals(generalNotifierType.isShowTechnicalInformation()); + boolean techInfo = Boolean.TRUE.equals(configuration.isShowTechnicalInformation()); StringBuilder body = new StringBuilder(); - ResourceObjectEvent resourceObjectEvent = (ResourceObjectEvent) event; - - FocusType owner = (FocusType) resourceObjectEvent.getRequesteeObject(); - ResourceOperationDescription rod = resourceObjectEvent.getAccountOperationDescription(); + FocusType owner = (FocusType) event.getRequesteeObject(); + ResourceOperationDescription rod = event.getAccountOperationDescription(); + //noinspection unchecked ObjectDelta delta = (ObjectDelta) rod.getObjectDelta(); - boolean isAccount = resourceObjectEvent.isShadowKind(ShadowKindType.ACCOUNT); + boolean isAccount = event.isShadowKind(ShadowKindType.ACCOUNT); String objectTypeDescription = isAccount ? "account" : "resource object"; String userOrOwner = owner instanceof UserType ? "User" : "Owner"; body.append("Notification about ").append(objectTypeDescription).append("-related operation\n\n"); if (isAccount) { if (owner != null) { - body.append(userOrOwner).append(": ").append(resourceObjectEvent.getRequesteeDisplayName()); + body.append(userOrOwner).append(": ").append(event.getRequesteeDisplayName()); body.append(" (").append(owner.getName()).append(", oid ").append(owner.getOid()).append(")\n"); } else { body.append(userOrOwner).append(": unknown\n"); } } - body.append("Notification created on: " + new Date() + "\n\n"); - body.append("Resource: " + resourceObjectEvent.getResourceName() + " (oid " + resourceObjectEvent.getResourceOid() + ")\n"); + body.append("Notification created on: ").append(new Date()).append("\n\n"); + body.append("Resource: ").append(event.getResourceName()).append(" (oid ").append(event.getResourceOid()).append(")\n"); boolean named; if (rod.getCurrentShadow() != null && rod.getCurrentShadow().asObjectable().getName() != null) { if (isAccount) { - body.append("Account: " + rod.getCurrentShadow().asObjectable().getName() + "\n"); + body.append("Account: ").append(rod.getCurrentShadow().asObjectable().getName()).append("\n"); } else { - body.append("Resource object: " + rod.getCurrentShadow().asObjectable().getName() + " (kind: " + rod.getCurrentShadow().asObjectable().getKind() + ")\n"); + body.append("Resource object: ").append(rod.getCurrentShadow().asObjectable().getName()).append(" (kind: ").append(rod.getCurrentShadow().asObjectable().getKind()).append(")\n"); } named = true; } else { @@ -136,35 +124,35 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S body.append("\n"); if (isAccount) { - body.append((named ? "The" : "An") + " account "); + body.append(named ? "The" : "An").append(" account "); } else { - body.append((named ? "The" : "A") + " resource object "); + body.append(named ? "The" : "A").append(" resource object "); } - switch (resourceObjectEvent.getOperationStatus()) { + switch (event.getOperationStatus()) { case SUCCESS: body.append("has been successfully "); break; case IN_PROGRESS: body.append("has been ATTEMPTED to be "); break; case FAILURE: body.append("FAILED to be "); break; } - final boolean watchSynchronizationAttributes = isWatchSynchronizationAttributes((SimpleResourceObjectNotifierType) generalNotifierType); - final boolean watchAuxiliaryAttributes = isWatchAuxiliaryAttributes(generalNotifierType); + final boolean watchSynchronizationAttributes = isWatchSynchronizationAttributes(configuration); + final boolean watchAuxiliaryAttributes = isWatchAuxiliaryAttributes(configuration); if (delta.isAdd()) { body.append("created on the resource with attributes:\n"); - body.append(resourceObjectEvent.getContentAsFormattedList(watchSynchronizationAttributes, watchAuxiliaryAttributes)); + body.append(event.getContentAsFormattedList(watchSynchronizationAttributes, watchAuxiliaryAttributes)); body.append("\n"); } else if (delta.isModify()) { body.append("modified on the resource. Modified attributes are:\n"); - body.append(resourceObjectEvent.getContentAsFormattedList(watchSynchronizationAttributes, watchAuxiliaryAttributes)); + body.append(event.getContentAsFormattedList(watchSynchronizationAttributes, watchAuxiliaryAttributes)); body.append("\n"); } else if (delta.isDelete()) { body.append("removed from the resource.\n\n"); } - if (resourceObjectEvent.getOperationStatus() == OperationStatus.IN_PROGRESS) { + if (event.getOperationStatus() == OperationStatus.IN_PROGRESS) { body.append("The operation will be retried.\n\n"); - } else if (resourceObjectEvent.getOperationStatus() == OperationStatus.FAILURE) { - body.append("Error: " + resourceObjectEvent.getAccountOperationDescription().getResult().getMessage() + "\n\n"); + } else if (event.getOperationStatus() == OperationStatus.FAILURE) { + body.append("Error: ").append(event.getAccountOperationDescription().getResult().getMessage()).append("\n\n"); } body.append("\n\n"); @@ -179,49 +167,8 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S return body.toString(); } - -// private String getLocalPart(QName name) { -// if (name == null) { -// return null; -// } else { -// return name.getLocalPart(); -// } -// } -// -// private String getResourceName(AccountShadowType account) { -// String oid = null; -// if (account.getResource() != null) { -// if (account.getResource().getName() != null) { -// return account.getResource().getName().getOrig(); -// } -// oid = account.getResource().getOid(); -// } else { -// if (account.getResourceRef() != null) { -// oid = account.getResourceRef().getOid(); -// } -// } -// if (oid == null) { -// return ("(unknown resource)"); -// } -// return NotificationsUtil.getResourceNameFromRepo(cacheRepositoryService, oid, new OperationResult("dummy")); -// } -// -// private void listAccounts(StringBuilder messageText, List lines) { -// boolean first = true; -// for (String line : lines) { -// if (first) { -// first = false; -// } else { -// messageText.append(",\n"); -// } -// messageText.append(line); -// } -// messageText.append(".\n\n"); -// } - @Override protected Trace getLogger() { return LOGGER; } - } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleReviewerNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleReviewerNotifier.java index 98ec76c20b9..da317635080 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleReviewerNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleReviewerNotifier.java @@ -7,79 +7,71 @@ package com.evolveum.midpoint.notifications.impl.notifiers; -import com.evolveum.midpoint.model.api.expr.MidpointFunctions; +import org.apache.commons.lang.time.DurationFormatUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.notifications.api.events.CertReviewEvent; -import com.evolveum.midpoint.notifications.api.events.Event; import com.evolveum.midpoint.notifications.impl.helpers.CertHelper; import com.evolveum.midpoint.prism.xml.XmlTypeConverter; import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.util.CertCampaignTypeUtil; import com.evolveum.midpoint.schema.util.ApprovalContextUtil; +import com.evolveum.midpoint.schema.util.CertCampaignTypeUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCampaignType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationStageDefinitionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationStageType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SimpleReviewerNotifierType; -import org.apache.commons.lang.time.DurationFormatUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; /** * Various reviewer-level notifications. - * - * @author mederly */ @Component -public class SimpleReviewerNotifier extends GeneralNotifier { +public class SimpleReviewerNotifier extends AbstractGeneralNotifier { private static final Trace LOGGER = TraceManager.getTrace(SimpleReviewerNotifier.class); - @Autowired private MidpointFunctions midpointFunctions; @Autowired private CertHelper certHelper; - @PostConstruct - public void init() { - register(SimpleReviewerNotifierType.class); + @Override + public Class getEventType() { + return CertReviewEvent.class; } @Override - protected boolean quickCheckApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - if (!(event instanceof CertReviewEvent)) { - LOGGER.trace("SimpleReviewerNotifier is not applicable for this kind of event, continuing in the handler chain; event class = " + event.getClass()); - return false; - } - CertReviewEvent reviewEvent = (CertReviewEvent) event; - if (reviewEvent.isAdd()) { + public Class getEventHandlerConfigurationType() { + return SimpleReviewerNotifierType.class; + } + + @Override + protected boolean quickCheckApplicability(CertReviewEvent event, SimpleReviewerNotifierType configuration, OperationResult result) { + if (event.isAdd()) { return true; } - if (reviewEvent.isDelete()) { + if (event.isDelete()) { return false; // such events are not even created } - AccessCertificationStageDefinitionType stageDef = reviewEvent.getCurrentStageDefinition(); + AccessCertificationStageDefinitionType stageDef = event.getCurrentStageDefinition(); if (stageDef == null) { return false; // should not occur } if (Boolean.FALSE.equals(stageDef.isNotifyOnlyWhenNoDecision())) { return true; } - if (reviewEvent.getCasesAwaitingResponseFromRequestee().isEmpty()) { + if (event.getCasesAwaitingResponseFromActualReviewer().isEmpty()) { return false; } return true; } @Override - protected String getSubject(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { - CertReviewEvent reviewEvent = (CertReviewEvent) event; - String campaignName = reviewEvent.getCampaignName(); - if (reviewEvent.isAdd()) { + protected String getSubject(CertReviewEvent event, SimpleReviewerNotifierType configuration, String transport, Task task, OperationResult result) { + String campaignName = event.getCampaignName(); + if (event.isAdd()) { return "Your review is requested in campaign " + campaignName; - } else if (reviewEvent.isModify()) { + } else if (event.isModify()) { return "Deadline for your review in campaign " + campaignName + " is approaching"; } else { throw new IllegalStateException("Unexpected review event type: neither ADD nor MODIFY"); @@ -87,20 +79,19 @@ protected String getSubject(Event event, GeneralNotifierType generalNotifierType } @Override - protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { + protected String getBody(CertReviewEvent event, SimpleReviewerNotifierType configuration, String transport, Task task, OperationResult result) { StringBuilder body = new StringBuilder(); - CertReviewEvent reviewEvent = (CertReviewEvent) event; - AccessCertificationCampaignType campaign = reviewEvent.getCampaign(); + AccessCertificationCampaignType campaign = event.getCampaign(); body.append("You have been requested to provide a review in a certification campaign."); body.append("\n"); - body.append("\nReviewer: ").append(valueFormatter.formatUserName(reviewEvent.getActualReviewer(), result)); - if (!reviewEvent.getActualReviewer().getOid().equals(reviewEvent.getRequesteeOid())) { - body.append("\nDeputy: ").append(valueFormatter.formatUserName(reviewEvent.getRequestee(), result)); + body.append("\nReviewer: ").append(valueFormatter.formatUserName(event.getActualReviewer(), result)); + if (!event.getActualReviewer().getOid().equals(event.getRequesteeOid())) { + body.append("\nDeputy: ").append(valueFormatter.formatUserName(event.getRequestee(), result)); } body.append("\n"); - body.append("\nCampaign: ").append(certHelper.getCampaignNameAndOid(reviewEvent)); - body.append("\nState: ").append(certHelper.formatState(reviewEvent)); + body.append("\nCampaign: ").append(certHelper.getCampaignNameAndOid(event)); + body.append("\nState: ").append(certHelper.formatState(event)); body.append("\n\n"); AccessCertificationStageType stage = CertCampaignTypeUtil.getCurrentStage(campaign); if (stage != null) { @@ -112,7 +103,7 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S if (stage.getDeadline() != null) { long delta = XmlTypeConverter.toMillis(stage.getDeadline()) - System.currentTimeMillis(); if (delta > 0) { - if (reviewEvent.isModify()) { + if (event.isModify()) { body.append("\n\nThis is to notify you that the stage ends in "); } else { body.append("\n\nThe stage ends in "); @@ -125,8 +116,8 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S } } body.append("\n\n"); - body.append("There are ").append(reviewEvent.getCases().size()).append(" cases to be reviewed by you. "); - body.append("Out of them, ").append(reviewEvent.getCasesAwaitingResponseFromActualReviewer().size()).append(" are still waiting for your response."); + body.append("There are ").append(event.getCases().size()).append(" cases to be reviewed by you. "); + body.append("Out of them, ").append(event.getCasesAwaitingResponseFromActualReviewer().size()).append(" are still waiting for your response."); } return body.toString(); @@ -136,5 +127,4 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S protected Trace getLogger() { return LOGGER; } - } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleTaskNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleTaskNotifier.java index 3ea14d86baa..a934c992c3c 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleTaskNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleTaskNotifier.java @@ -7,69 +7,51 @@ package com.evolveum.midpoint.notifications.impl.notifiers; -import com.evolveum.midpoint.notifications.api.events.Event; +import java.util.Date; + +import org.apache.commons.lang.StringUtils; +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.notifications.api.events.TaskEvent; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SimpleTaskNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -import org.apache.commons.lang.StringUtils; -import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; -import java.util.Date; - -/** - * @author mederly - */ @Component -public class SimpleTaskNotifier extends GeneralNotifier { +public class SimpleTaskNotifier extends AbstractGeneralNotifier { private static final Trace LOGGER = TraceManager.getTrace(SimpleTaskNotifier.class); - @PostConstruct - public void init() { - register(SimpleTaskNotifierType.class); - } - @Override - protected boolean quickCheckApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - if (!(event instanceof TaskEvent)) { - LOGGER.trace("{} is not applicable for this kind of event, continuing in the handler chain; event class = {}", getClass().getSimpleName(), event.getClass()); - return false; - } - return true; + public Class getEventType() { + return TaskEvent.class; } @Override - protected boolean checkApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - return true; + public Class getEventHandlerConfigurationType() { + return SimpleTaskNotifierType.class; } @Override - protected String getSubject(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { - final TaskEvent taskEvent = (TaskEvent) event; - final String taskName = PolyString.getOrig(taskEvent.getTask().getName()); - + protected String getSubject(TaskEvent event, SimpleTaskNotifierType configuration, String transport, Task task, OperationResult result) { + String taskName = PolyString.getOrig(event.getTask().getName()); if (event.isAdd()) { return "Task '" + taskName + "' start notification"; } else if (event.isDelete()) { - return "Task '" + taskName + "' finish notification: " + taskEvent.getOperationResultStatus(); + return "Task '" + taskName + "' finish notification: " + event.getOperationResultStatus(); } else { return "(unknown " + taskName + " operation)"; } } @Override - protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, Task opTask, OperationResult opResult) throws SchemaException { - final TaskEvent taskEvent = (TaskEvent) event; - final Task task = taskEvent.getTask(); + protected String getBody(TaskEvent event, SimpleTaskNotifierType configuration, String transport, Task opTask, OperationResult opResult) { + final Task task = event.getTask(); final String taskName = PolyString.getOrig(task.getName()); StringBuilder body = new StringBuilder(); @@ -77,15 +59,15 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S body.append("Notification about task-related operation.\n\n"); body.append("Task: ").append(taskName).append("\n"); body.append("Handler: ").append(task.getHandlerUri()).append("\n\n"); - if (taskEvent.getTaskRunResult() != null) { - body.append("Run result status: ").append(taskEvent.getTaskRunResult().getRunResultStatus()).append("\n"); + if (event.getTaskRunResult() != null) { + body.append("Run result status: ").append(event.getTaskRunResult().getRunResultStatus()).append("\n"); } - body.append("Status: ").append(taskEvent.getOperationResultStatus()).append("\n"); - String message = taskEvent.getMessage(); + body.append("Status: ").append(event.getOperationResultStatus()).append("\n"); + String message = event.getMessage(); if (StringUtils.isNotBlank(message)) { body.append("Message: ").append(message).append("\n"); } - body.append("Progress: ").append(taskEvent.getProgress()).append("\n"); + body.append("Progress: ").append(event.getProgress()).append("\n"); body.append("\n"); body.append("Notification created on: ").append(new Date()).append("\n\n"); @@ -108,5 +90,4 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S protected Trace getLogger() { return LOGGER; } - } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleUserNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleUserNotifier.java index de5ad8032d3..9211712fb5e 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleUserNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleUserNotifier.java @@ -7,41 +7,26 @@ package com.evolveum.midpoint.notifications.impl.notifiers; -import com.evolveum.midpoint.notifications.api.events.Event; -import com.evolveum.midpoint.notifications.api.events.ModelEvent; -import com.evolveum.midpoint.schema.result.OperationResult; +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SimpleUserNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; - -/** - * @author mederly - */ @Component -public class SimpleUserNotifier extends SimpleFocalObjectNotifier { +public class SimpleUserNotifier extends AbstractFocalObjectNotifier { private static final Trace LOGGER = TraceManager.getTrace(SimpleUserNotifier.class); - @PostConstruct - public void init() { - register(SimpleUserNotifierType.class); + @Override + public Class getEventHandlerConfigurationType() { + return SimpleUserNotifierType.class; } @Override - protected boolean quickCheckApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - if (!super.quickCheckApplicability(event, generalNotifierType, result)) { - return false; - } - if (!((ModelEvent) event).getFocusContext().isOfType(UserType.class)) { - LOGGER.trace("Focus context type is not of UserType; skipping the notification"); - return false; - } - return true; + Class getFocusClass() { + return UserType.class; } @Override diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleWorkflowNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleWorkflowNotifier.java index 6d282468c46..285057c2af8 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleWorkflowNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleWorkflowNotifier.java @@ -7,25 +7,24 @@ package com.evolveum.midpoint.notifications.impl.notifiers; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.apache.commons.lang3.time.DurationFormatUtils; +import org.jetbrains.annotations.Nullable; +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.notifications.api.events.*; import com.evolveum.midpoint.prism.util.PrismUtil; import com.evolveum.midpoint.prism.xml.XmlTypeConverter; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ApprovalContextUtil; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import org.apache.commons.lang3.time.DurationFormatUtils; -import org.jetbrains.annotations.Nullable; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import javax.xml.datatype.XMLGregorianCalendar; -import java.util.Date; -import java.util.List; -import java.util.stream.Collectors; /** * Default implementation of a notifier dealing with workflow events (related to both work items and process instances). @@ -33,26 +32,22 @@ * @author mederly */ @Component -public class SimpleWorkflowNotifier extends GeneralNotifier { +public class SimpleWorkflowNotifier extends AbstractGeneralNotifier { private static final Trace LOGGER = TraceManager.getTrace(SimpleWorkflowNotifier.class); - @PostConstruct - public void init() { - register(SimpleWorkflowNotifierType.class); + @Override + public Class getEventType() { + return WorkflowEvent.class; } @Override - protected boolean quickCheckApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - if (!(event instanceof WorkflowEvent)) { - LOGGER.trace("SimpleWorkflowNotifier is not applicable for this kind of event, continuing in the handler chain; event class = " + event.getClass()); - return false; - } - return true; + public Class getEventHandlerConfigurationType() { + return SimpleWorkflowNotifierType.class; } @Override - protected UserType getDefaultRecipient(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { + protected UserType getDefaultRecipient(WorkflowEvent event, SimpleWorkflowNotifierType configuration, OperationResult result) { @Nullable SimpleObjectRef recipientRef; if (event instanceof WorkflowProcessEvent) { recipientRef = event.getRequester(); @@ -70,18 +65,17 @@ protected UserType getDefaultRecipient(Event event, GeneralNotifierType generalN } @Override - protected String getSubject(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { + protected String getSubject(WorkflowEvent event, SimpleWorkflowNotifierType configuration, String transport, Task task, OperationResult result) { if (event instanceof WorkflowProcessEvent) { return event.isAdd() ? "Workflow process instance has been started" : "Workflow process instance has finished"; } else if (event instanceof WorkItemEvent) { - return getSubjectFromWorkItemEvent((WorkItemEvent) event, generalNotifierType, transport, task, result); + return getSubjectFromWorkItemEvent((WorkItemEvent) event); } else { throw new UnsupportedOperationException("Unsupported event type for event=" + event); } } - private String getSubjectFromWorkItemEvent(WorkItemEvent event, GeneralNotifierType generalNotifierType, String transport, - Task task, OperationResult result) { + private String getSubjectFromWorkItemEvent(WorkItemEvent event) { if (event instanceof WorkItemLifecycleEvent) { if (event.isAdd()) { return "A new work item has been created"; @@ -118,40 +112,39 @@ private String getSubjectFromWorkItemEvent(WorkItemEvent event, GeneralNotifierT } @Override - protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) throws SchemaException { + protected String getBody(WorkflowEvent event, SimpleWorkflowNotifierType configuration, + String transport, Task task, OperationResult result) { - WorkflowEvent workflowEvent = (WorkflowEvent) event; - - boolean techInfo = Boolean.TRUE.equals(generalNotifierType.isShowTechnicalInformation()); + boolean techInfo = Boolean.TRUE.equals(configuration.isShowTechnicalInformation()); StringBuilder body = new StringBuilder(); - body.append(getSubject(event, generalNotifierType, transport, task, result)); + body.append(getSubject(event, configuration, transport, task, result)); body.append("\n\n"); - appendGeneralInformation(body, workflowEvent); // process instance name, work item name, stage, escalation level + appendGeneralInformation(body, event); // process instance name, work item name, stage, escalation level - if (workflowEvent instanceof WorkItemEvent) { - WorkItemEvent workItemEvent = (WorkItemEvent) workflowEvent; + if (event instanceof WorkItemEvent) { + WorkItemEvent workItemEvent = (WorkItemEvent) event; appendAssigneeInformation(body, workItemEvent, result); appendResultAndOriginInformation(body, workItemEvent, result); appendDeadlineInformation(body, workItemEvent); } else { - appendResultInformation(body, workflowEvent, true); + appendResultInformation(body, event, true); } body.append("\nNotification created on: ").append(new Date()).append("\n\n"); if (techInfo) { body.append("----------------------------------------\n"); body.append("Technical information:\n\n"); - if (workflowEvent instanceof WorkItemEvent) { - WorkItemEvent workItemEvent = (WorkItemEvent) workflowEvent; + if (event instanceof WorkItemEvent) { + WorkItemEvent workItemEvent = (WorkItemEvent) event; body.append("WorkItem:\n") .append(PrismUtil.serializeQuietly(prismContext, workItemEvent.getWorkItem())) .append("\n"); } body.append("Workflow context:\n") - .append(PrismUtil.serializeQuietly(prismContext, ((WorkflowEvent) event).getApprovalContext())); + .append(PrismUtil.serializeQuietly(prismContext, event.getApprovalContext())); } return body.toString(); } @@ -188,7 +181,7 @@ private void appendDeadlineInformation(StringBuilder sb, WorkItemEvent event) { } } - void appendDeadlineInformation(StringBuilder sb, AbstractWorkItemType workItem) { + private void appendDeadlineInformation(StringBuilder sb, AbstractWorkItemType workItem) { XMLGregorianCalendar deadline = workItem.getDeadline(); long before = XmlTypeConverter.toMillis(deadline) - System.currentTimeMillis(); long beforeRounded = Math.round((double) before / 60000.0) * 60000L; @@ -263,6 +256,7 @@ private void appendAssigneeInformation(StringBuilder sb, WorkItemEvent event, Op } // a bit of heuristics... + @SuppressWarnings("SimplifiableIfStatement") private boolean isDone(WorkItemEvent event) { if (event instanceof WorkItemLifecycleEvent) { return event.isDelete(); diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/TimeValidityNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/TimeValidityNotifier.java index cea9f18a221..fbb1f9c977f 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/TimeValidityNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/TimeValidityNotifier.java @@ -7,18 +7,13 @@ package com.evolveum.midpoint.notifications.impl.notifiers; -import javax.annotation.PostConstruct; - import org.springframework.stereotype.Component; -import com.evolveum.midpoint.notifications.api.events.Event; import com.evolveum.midpoint.notifications.api.events.PolicyRuleEvent; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.PolicyConstraintsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.TimeValidityNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; @@ -28,60 +23,48 @@ * @author katkav */ @Component -public class TimeValidityNotifier extends SimplePolicyRuleNotifier { +public class TimeValidityNotifier extends AbstractPolicyRuleNotifier { private static final Trace LOGGER = TraceManager.getTrace(TimeValidityNotifier.class); - @PostConstruct - public void init() { - register(TimeValidityNotifierType.class); + @Override + public Class getEventHandlerConfigurationType() { + return TimeValidityNotifierType.class; } @Override - protected boolean quickCheckApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - if (!(event instanceof PolicyRuleEvent)) { - return false; - } - PolicyRuleEvent modelEvent = (PolicyRuleEvent) event; - - return UserType.class.isAssignableFrom(modelEvent.getRequesteeObject().getClass()); + protected boolean quickCheckApplicability(PolicyRuleEvent event, TimeValidityNotifierType configuration, OperationResult result) { + return UserType.class.isAssignableFrom(event.getRequesteeObject().getClass()); } @Override - protected boolean checkApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - PolicyRuleEvent ruleEvent = (PolicyRuleEvent) event; - PolicyConstraintsType policyConstraints = ruleEvent.getPolicyRule().getPolicyConstraints(); + protected boolean checkApplicability(PolicyRuleEvent event, TimeValidityNotifierType configuration, OperationResult result) { + PolicyConstraintsType policyConstraints = event.getPolicyRule().getPolicyConstraints(); return policyConstraints != null && policyConstraints.getObjectTimeValidity() != null && !policyConstraints.getObjectTimeValidity().isEmpty(); } @Override - protected String getSubject(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, + protected String getSubject(PolicyRuleEvent event, TimeValidityNotifierType configuration, String transport, Task task, OperationResult result) { - - return "Planned deactivation of user " + getUserName(event); } @Override - protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, - OperationResult result) throws SchemaException { - + protected String getBody(PolicyRuleEvent event, TimeValidityNotifierType configuration, String transport, Task task, + OperationResult result) { return "User " + getUserName(event) + " is going to be deactivated on " + getUser(event).getActivation().getValidTo(); - } - private String getUserName(Event event){ + private String getUserName(PolicyRuleEvent event) { UserType user = getUser(event); PolyStringType username = user.getName(); return username.getOrig(); } - private UserType getUser(Event event){ - PolicyRuleEvent taskEvent = (PolicyRuleEvent) event; - UserType user = (UserType) taskEvent.getRequesteeObject(); - return user; + private UserType getUser(PolicyRuleEvent event) { + return (UserType) event.getRequesteeObject(); } @Override diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/UserPasswordNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/UserPasswordNotifier.java index e6e8b7010ba..fec2a14563e 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/UserPasswordNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/UserPasswordNotifier.java @@ -7,40 +7,41 @@ package com.evolveum.midpoint.notifications.impl.notifiers; -import com.evolveum.midpoint.notifications.api.events.Event; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + import com.evolveum.midpoint.notifications.api.events.ModelEvent; import com.evolveum.midpoint.notifications.impl.NotificationFunctionsImpl; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserPasswordNotifierType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; /** - * @author mederly + * TODO generalize to non-user principals */ @Component -public class UserPasswordNotifier extends GeneralNotifier { +public class UserPasswordNotifier extends AbstractGeneralNotifier { private static final Trace LOGGER = TraceManager.getTrace(UserPasswordNotifier.class); - @Autowired - private NotificationFunctionsImpl notificationsUtil; + @Autowired private NotificationFunctionsImpl notificationsUtil; - @PostConstruct - public void init() { - register(UserPasswordNotifierType.class); + @Override + public Class getEventType() { + return ModelEvent.class; } @Override - protected boolean quickCheckApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { - if (!(event instanceof ModelEvent) || !((ModelEvent) event).hasFocusOfType(UserType.class)) { + public Class getEventHandlerConfigurationType() { + return UserPasswordNotifierType.class; + } + + @Override + protected boolean quickCheckApplicability(ModelEvent event, UserPasswordNotifierType configuration, OperationResult result) { + if (!event.hasFocusOfType(UserType.class)) { LOGGER.trace("UserPasswordNotifier is not applicable for this kind of event, continuing in the handler chain; event class = " + event.getClass()); return false; } else { @@ -49,21 +50,22 @@ protected boolean quickCheckApplicability(Event event, GeneralNotifierType gener } @Override - protected boolean checkApplicability(Event event, GeneralNotifierType generalNotifierType, OperationResult result) { + protected boolean checkApplicability(ModelEvent event, UserPasswordNotifierType configuration, OperationResult result) { if (!event.isAlsoSuccess()) { // TODO LOGGER.trace("Operation was not successful, exiting."); return false; + } else { + return event.getFocusPassword() != null; // logging is done in the called method } - return event.getFocusPassword() != null; // logging is done in the called method } @Override - protected String getSubject(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { + protected String getSubject(ModelEvent event, UserPasswordNotifierType configuration, String transport, Task task, OperationResult result) { return "User password notification"; } @Override - protected String getBody(Event event, GeneralNotifierType generalNotifierType, String transport, Task task, OperationResult result) { + protected String getBody(ModelEvent event, UserPasswordNotifierType configuration, String transport, Task task, OperationResult result) { return "Password for user " + notificationsUtil.getObjectType(event.getRequestee(), false, result).getName() + " is: " + event.getFocusPassword(); }