001
014
015 package com.liferay.portal.systemevent;
016
017 import com.liferay.portal.kernel.lar.StagedModelType;
018 import com.liferay.portal.kernel.log.Log;
019 import com.liferay.portal.kernel.log.LogFactoryUtil;
020 import com.liferay.portal.kernel.systemevent.SystemEvent;
021 import com.liferay.portal.kernel.systemevent.SystemEventHierarchyEntry;
022 import com.liferay.portal.kernel.systemevent.SystemEventHierarchyEntryThreadLocal;
023 import com.liferay.portal.kernel.util.StringBundler;
024 import com.liferay.portal.kernel.util.StringPool;
025 import com.liferay.portal.model.AuditedModel;
026 import com.liferay.portal.model.ClassedModel;
027 import com.liferay.portal.model.GroupedModel;
028 import com.liferay.portal.model.StagedModel;
029 import com.liferay.portal.model.SystemEventConstants;
030 import com.liferay.portal.model.TypedModel;
031 import com.liferay.portal.service.SystemEventLocalServiceUtil;
032 import com.liferay.portal.spring.aop.AnnotationChainableMethodAdvice;
033
034 import java.io.Serializable;
035
036 import java.lang.annotation.Annotation;
037 import java.lang.reflect.Method;
038
039 import org.aopalliance.intercept.MethodInvocation;
040
041
044 public class SystemEventAdvice
045 extends AnnotationChainableMethodAdvice<SystemEvent> {
046
047 @Override
048 public void afterReturning(MethodInvocation methodInvocation, Object result)
049 throws Throwable {
050
051 SystemEvent systemEvent = findAnnotation(methodInvocation);
052
053 if ((systemEvent == _nullSystemEvent) || !systemEvent.send()) {
054 return;
055 }
056
057 if (!isValid(methodInvocation, PHASE_AFTER_RETURNING)) {
058 return;
059 }
060
061 Object[] arguments = methodInvocation.getArguments();
062
063 ClassedModel classedModel = (ClassedModel)arguments[0];
064
065 long groupId = getGroupId(classedModel);
066
067 String className = getClassName(classedModel);
068
069 String referrerClassName = null;
070
071 if (classedModel instanceof TypedModel) {
072 TypedModel typedModel = (TypedModel)classedModel;
073
074 referrerClassName = typedModel.getClassName();
075 }
076
077 long classPK = getClassPK(classedModel);
078
079 SystemEventHierarchyEntry systemEventHierarchyEntry =
080 SystemEventHierarchyEntryThreadLocal.peek();
081
082 if ((systemEventHierarchyEntry != null) &&
083 systemEventHierarchyEntry.hasTypedModel(className, classPK)) {
084
085 if (groupId > 0) {
086 SystemEventLocalServiceUtil.addSystemEvent(
087 0, groupId, systemEventHierarchyEntry.getClassName(),
088 classPK, systemEventHierarchyEntry.getUuid(),
089 referrerClassName, systemEvent.type(),
090 systemEventHierarchyEntry.getExtraData());
091 }
092 else {
093 SystemEventLocalServiceUtil.addSystemEvent(
094 getCompanyId(classedModel),
095 systemEventHierarchyEntry.getClassName(), classPK,
096 systemEventHierarchyEntry.getUuid(), referrerClassName,
097 systemEvent.type(),
098 systemEventHierarchyEntry.getExtraData());
099 }
100 }
101 else if (groupId > 0) {
102 SystemEventLocalServiceUtil.addSystemEvent(
103 0, groupId, className, classPK, getUuid(classedModel),
104 referrerClassName, systemEvent.type(), StringPool.BLANK);
105 }
106 else {
107 SystemEventLocalServiceUtil.addSystemEvent(
108 getCompanyId(classedModel), className, classPK,
109 getUuid(classedModel), referrerClassName, systemEvent.type(),
110 StringPool.BLANK);
111 }
112 }
113
114 @Override
115 public Object before(MethodInvocation methodInvocation) throws Throwable {
116 SystemEvent systemEvent = findAnnotation(methodInvocation);
117
118 if (systemEvent == _nullSystemEvent) {
119 return null;
120 }
121
122 if (systemEvent.action() != SystemEventConstants.ACTION_NONE) {
123 if (!isValid(methodInvocation, PHASE_BEFORE)) {
124 return null;
125 }
126
127 Object[] arguments = methodInvocation.getArguments();
128
129 ClassedModel classedModel = (ClassedModel)arguments[0];
130
131 SystemEventHierarchyEntry systemEventHierarchyEntry =
132 SystemEventHierarchyEntryThreadLocal.push(
133 getClassName(classedModel), getClassPK(classedModel),
134 systemEvent.action());
135
136 if (systemEventHierarchyEntry != null) {
137 systemEventHierarchyEntry.setUuid(getUuid(classedModel));
138 }
139 }
140
141 return null;
142 }
143
144 @Override
145 public void duringFinally(MethodInvocation methodInvocation) {
146 SystemEvent systemEvent = findAnnotation(methodInvocation);
147
148 if (systemEvent == _nullSystemEvent) {
149 return;
150 }
151
152 if (!isValid(methodInvocation, PHASE_DURING_FINALLY)) {
153 return;
154 }
155
156 if (systemEvent.action() == SystemEventConstants.ACTION_NONE) {
157 return;
158 }
159
160 SystemEventHierarchyEntry systemEventHierarchyEntry =
161 SystemEventHierarchyEntryThreadLocal.peek();
162
163 if (systemEventHierarchyEntry == null) {
164 return;
165 }
166
167 Object[] arguments = methodInvocation.getArguments();
168
169 ClassedModel classedModel = (ClassedModel)arguments[0];
170
171 long classPK = getClassPK(classedModel);
172
173 if (classPK == 0) {
174 return;
175 }
176
177 if (systemEventHierarchyEntry.hasTypedModel(
178 getClassName(classedModel), classPK)) {
179
180 SystemEventHierarchyEntryThreadLocal.pop();
181 }
182 }
183
184 @Override
185 public SystemEvent getNullAnnotation() {
186 return _nullSystemEvent;
187 }
188
189 protected String getClassName(ClassedModel classedModel) {
190 String className = classedModel.getModelClassName();
191
192 if (classedModel instanceof StagedModel) {
193 StagedModel stagedModel = (StagedModel)classedModel;
194
195 StagedModelType stagedModelType = stagedModel.getStagedModelType();
196
197 className = stagedModelType.getClassName();
198 }
199
200 return className;
201 }
202
203 protected long getClassPK(ClassedModel classedModel) {
204 Serializable primaryKeyObj = classedModel.getPrimaryKeyObj();
205
206 if (!(primaryKeyObj instanceof Long)) {
207 return 0;
208 }
209
210 return (Long)primaryKeyObj;
211 }
212
213 protected long getCompanyId(ClassedModel classedModel) {
214 if (classedModel instanceof AuditedModel) {
215 AuditedModel auditedModel = (AuditedModel)classedModel;
216
217 return auditedModel.getCompanyId();
218 }
219
220 if (classedModel instanceof GroupedModel) {
221 GroupedModel groupedModel = (GroupedModel)classedModel;
222
223 return groupedModel.getCompanyId();
224 }
225
226 if (classedModel instanceof StagedModel) {
227 StagedModel stagedModel = (StagedModel)classedModel;
228
229 return stagedModel.getCompanyId();
230 }
231
232 return 0;
233 }
234
235 protected long getGroupId(ClassedModel classedModel) {
236 if (!(classedModel instanceof GroupedModel)) {
237 return 0;
238 }
239
240 GroupedModel groupedModel = (GroupedModel)classedModel;
241
242 return groupedModel.getGroupId();
243 }
244
245 protected String getUuid(ClassedModel classedModel) throws Exception {
246 String uuid = null;
247
248 if (classedModel instanceof StagedModel) {
249 StagedModel stagedModel = (StagedModel)classedModel;
250
251 uuid = stagedModel.getUuid();
252 }
253 else {
254 Class<?> modelClass = classedModel.getClass();
255
256 Method getUuidMethod = modelClass.getMethod(
257 "getUuid", new Class[0]);
258
259 if (getUuidMethod != null) {
260 uuid = (String)getUuidMethod.invoke(
261 classedModel, new Object[0]);
262 }
263 else {
264 uuid = StringPool.BLANK;
265 }
266 }
267
268 return uuid;
269 }
270
271 protected boolean isValid(MethodInvocation methodInvocation, int phase) {
272 Method method = methodInvocation.getMethod();
273
274 Class<?>[] parameterTypes = method.getParameterTypes();
275
276 if (parameterTypes.length == 0) {
277 if (_log.isDebugEnabled() && (phase == PHASE_BEFORE)) {
278 _log.debug(
279 "The method " + methodInvocation +
280 " must have at least one parameter");
281 }
282
283 return false;
284 }
285
286 Class<?> parameterType = parameterTypes[0];
287
288 if (!ClassedModel.class.isAssignableFrom(parameterType)) {
289 if (_log.isDebugEnabled() && (phase == PHASE_BEFORE)) {
290 _log.debug(
291 "The first parameter of " + methodInvocation +
292 " must implement ClassedModel");
293 }
294
295 return false;
296 }
297
298 Object[] arguments = methodInvocation.getArguments();
299
300 ClassedModel classedModel = (ClassedModel)arguments[0];
301
302 if (!(classedModel.getPrimaryKeyObj() instanceof Long)) {
303 if (_log.isDebugEnabled() && (phase == PHASE_BEFORE)) {
304 _log.debug(
305 "The first parameter of " + methodInvocation +
306 " must be a long");
307 }
308
309 return false;
310 }
311
312 if (phase != PHASE_AFTER_RETURNING) {
313 return true;
314 }
315
316 if (!AuditedModel.class.isAssignableFrom(parameterType) &&
317 !GroupedModel.class.isAssignableFrom(parameterType) &&
318 !StagedModel.class.isAssignableFrom(parameterType)) {
319
320 if (_log.isDebugEnabled()) {
321 StringBundler sb = new StringBundler(4);
322
323 sb.append("If send is true, the first parameter of ");
324 sb.append(methodInvocation);
325 sb.append(" must implement AuditedModel, GroupedModel, or ");
326 sb.append("StagedModel");
327
328 _log.debug(sb.toString());
329 }
330
331 return false;
332 }
333
334 return true;
335 }
336
337 private static final int PHASE_AFTER_RETURNING = 1;
338
339 private static final int PHASE_BEFORE = 0;
340
341 private static final int PHASE_DURING_FINALLY = 2;
342
343 private static Log _log = LogFactoryUtil.getLog(SystemEventAdvice.class);
344
345 private static SystemEvent _nullSystemEvent = new SystemEvent() {
346
347 @Override
348 public Class<? extends Annotation> annotationType() {
349 return SystemEvent.class;
350 }
351
352 @Override
353 public int action() {
354 return SystemEventConstants.ACTION_NONE;
355 }
356
357 @Override
358 public boolean send() {
359 return false;
360 }
361
362 @Override
363 public int type() {
364 return 0;
365 }
366
367 };
368
369 }