1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.core.logic;
20
21 import java.lang.reflect.Method;
22 import org.apache.commons.lang3.StringUtils;
23 import org.apache.syncope.common.lib.types.AuditElements;
24 import org.apache.syncope.core.provisioning.api.AuditManager;
25 import org.apache.syncope.core.provisioning.api.event.AfterHandlingEvent;
26 import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
27 import org.apache.syncope.core.spring.security.AuthContextUtils;
28 import org.aspectj.lang.ProceedingJoinPoint;
29 import org.aspectj.lang.annotation.Around;
30 import org.aspectj.lang.annotation.Aspect;
31 import org.aspectj.lang.reflect.MethodSignature;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 @Aspect
36 public class LogicInvocationHandler {
37
38 protected static final Logger LOG = LoggerFactory.getLogger(LogicInvocationHandler.class);
39
40 protected final NotificationManager notificationManager;
41
42 protected final AuditManager auditManager;
43
44 public LogicInvocationHandler(final NotificationManager notificationManager, final AuditManager auditManager) {
45 this.notificationManager = notificationManager;
46 this.auditManager = auditManager;
47 }
48
49 @Around("execution(* org.apache.syncope.core.logic.AbstractLogic+.*(..))")
50 public Object around(final ProceedingJoinPoint joinPoint) throws Throwable {
51 Class<?> clazz = joinPoint.getTarget().getClass();
52
53 Object[] input = joinPoint.getArgs();
54
55 String category = clazz.getSimpleName();
56
57 MethodSignature ms = (MethodSignature) joinPoint.getSignature();
58 Method method = ms.getMethod();
59
60 String event = joinPoint.getSignature().getName();
61
62 boolean notificationsAvailable = notificationManager.notificationsAvailable(
63 AuditElements.EventCategoryType.LOGIC, category, null, event);
64 boolean auditRequested = auditManager.auditRequested(
65 AuthContextUtils.getUsername(), AuditElements.EventCategoryType.LOGIC, category, null, event);
66
67 AuditElements.Result condition = null;
68 Object output = null;
69 Object before = null;
70
71 try {
72 LOG.debug("Before {}.{}({})", clazz.getSimpleName(), event,
73 input == null || input.length == 0 ? StringUtils.EMPTY : input);
74
75 if (notificationsAvailable || auditRequested) {
76 try {
77 before = ((AbstractLogic) joinPoint.getTarget()).resolveBeanReference(method, input);
78 } catch (UnresolvedReferenceException ignore) {
79 LOG.debug("Unresolved bean reference ...");
80 }
81 }
82
83 output = joinPoint.proceed();
84 condition = AuditElements.Result.SUCCESS;
85
86 LOG.debug("After returning {}.{}: {}", clazz.getSimpleName(), event, output);
87 return output;
88 } catch (Throwable t) {
89 output = t;
90 condition = AuditElements.Result.FAILURE;
91
92 LOG.debug("After throwing {}.{}", clazz.getSimpleName(), event);
93 throw t;
94 } finally {
95 if (notificationsAvailable || auditRequested) {
96 AfterHandlingEvent afterHandlingEvent = new AfterHandlingEvent(
97 AuthContextUtils.getWho(),
98 AuditElements.EventCategoryType.LOGIC,
99 category,
100 null,
101 event,
102 condition,
103 before,
104 output,
105 input);
106 AuthContextUtils.callAsAdmin(AuthContextUtils.getDomain(), () -> {
107 try {
108 notificationManager.createTasks(afterHandlingEvent);
109 auditManager.audit(afterHandlingEvent);
110 } catch (Throwable t) {
111 LOG.error("While managing Audit and Notifications", t);
112 }
113 return null;
114 });
115 }
116 }
117 }
118 }