/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.systemevent;
import com.liferay.exportimport.kernel.lar.StagedModelType;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.AuditedModel;
import com.liferay.portal.kernel.model.ClassedModel;
import com.liferay.portal.kernel.model.GroupedModel;
import com.liferay.portal.kernel.model.StagedModel;
import com.liferay.portal.kernel.model.SystemEventConstants;
import com.liferay.portal.kernel.model.TypedModel;
import com.liferay.portal.kernel.service.SystemEventLocalServiceUtil;
import com.liferay.portal.kernel.systemevent.SystemEvent;
import com.liferay.portal.kernel.systemevent.SystemEventHierarchyEntry;
import com.liferay.portal.kernel.systemevent.SystemEventHierarchyEntryThreadLocal;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.spring.aop.AnnotationChainableMethodAdvice;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInvocation;
/**
* @author Zsolt Berentey
*/
public class SystemEventAdvice
extends AnnotationChainableMethodAdvice<SystemEvent> {
@Override
public void afterReturning(MethodInvocation methodInvocation, Object result)
throws Throwable {
SystemEvent systemEvent = findAnnotation(methodInvocation);
if ((systemEvent == _nullSystemEvent) || !systemEvent.send()) {
return;
}
if (!isValid(methodInvocation, _PHASE_AFTER_RETURNING)) {
return;
}
Object[] arguments = methodInvocation.getArguments();
ClassedModel classedModel = (ClassedModel)arguments[0];
long groupId = getGroupId(classedModel);
String className = getClassName(classedModel);
String referrerClassName = null;
if (classedModel instanceof TypedModel) {
TypedModel typedModel = (TypedModel)classedModel;
referrerClassName = typedModel.getClassName();
}
long classPK = getClassPK(classedModel);
SystemEventHierarchyEntry systemEventHierarchyEntry =
SystemEventHierarchyEntryThreadLocal.peek();
if ((systemEventHierarchyEntry != null) &&
systemEventHierarchyEntry.hasTypedModel(className, classPK)) {
if (groupId > 0) {
SystemEventLocalServiceUtil.addSystemEvent(
0, groupId, systemEventHierarchyEntry.getClassName(),
classPK, systemEventHierarchyEntry.getUuid(),
referrerClassName, systemEvent.type(),
systemEventHierarchyEntry.getExtraData());
}
else {
SystemEventLocalServiceUtil.addSystemEvent(
getCompanyId(classedModel),
systemEventHierarchyEntry.getClassName(), classPK,
systemEventHierarchyEntry.getUuid(), referrerClassName,
systemEvent.type(),
systemEventHierarchyEntry.getExtraData());
}
}
else if (groupId > 0) {
SystemEventLocalServiceUtil.addSystemEvent(
0, groupId, className, classPK, getUuid(classedModel),
referrerClassName, systemEvent.type(), StringPool.BLANK);
}
else {
SystemEventLocalServiceUtil.addSystemEvent(
getCompanyId(classedModel), className, classPK,
getUuid(classedModel), referrerClassName, systemEvent.type(),
StringPool.BLANK);
}
}
@Override
public Object before(MethodInvocation methodInvocation) throws Throwable {
SystemEvent systemEvent = findAnnotation(methodInvocation);
if (systemEvent == _nullSystemEvent) {
return null;
}
if (systemEvent.action() != SystemEventConstants.ACTION_NONE) {
if (!isValid(methodInvocation, _PHASE_BEFORE)) {
return null;
}
Object[] arguments = methodInvocation.getArguments();
ClassedModel classedModel = (ClassedModel)arguments[0];
SystemEventHierarchyEntry systemEventHierarchyEntry =
SystemEventHierarchyEntryThreadLocal.push(
getClassName(classedModel), getClassPK(classedModel),
systemEvent.action());
if (systemEventHierarchyEntry != null) {
systemEventHierarchyEntry.setUuid(getUuid(classedModel));
}
}
return null;
}
@Override
public void duringFinally(MethodInvocation methodInvocation) {
SystemEvent systemEvent = findAnnotation(methodInvocation);
if (systemEvent == _nullSystemEvent) {
return;
}
if (!isValid(methodInvocation, _PHASE_DURING_FINALLY)) {
return;
}
if (systemEvent.action() == SystemEventConstants.ACTION_NONE) {
return;
}
Object[] arguments = methodInvocation.getArguments();
ClassedModel classedModel = (ClassedModel)arguments[0];
long classPK = getClassPK(classedModel);
if (classPK == 0) {
return;
}
SystemEventHierarchyEntryThreadLocal.pop(
getClassName(classedModel), classPK);
}
@Override
public SystemEvent getNullAnnotation() {
return _nullSystemEvent;
}
protected String getClassName(ClassedModel classedModel) {
String className = classedModel.getModelClassName();
if (classedModel instanceof StagedModel) {
StagedModel stagedModel = (StagedModel)classedModel;
StagedModelType stagedModelType = stagedModel.getStagedModelType();
className = stagedModelType.getClassName();
}
return className;
}
protected long getClassPK(ClassedModel classedModel) {
Serializable primaryKeyObj = classedModel.getPrimaryKeyObj();
if (!(primaryKeyObj instanceof Long)) {
return 0;
}
return (Long)primaryKeyObj;
}
protected long getCompanyId(ClassedModel classedModel) {
if (classedModel instanceof AuditedModel) {
AuditedModel auditedModel = (AuditedModel)classedModel;
return auditedModel.getCompanyId();
}
if (classedModel instanceof GroupedModel) {
GroupedModel groupedModel = (GroupedModel)classedModel;
return groupedModel.getCompanyId();
}
if (classedModel instanceof StagedModel) {
StagedModel stagedModel = (StagedModel)classedModel;
return stagedModel.getCompanyId();
}
return 0;
}
protected long getGroupId(ClassedModel classedModel) {
if (!(classedModel instanceof GroupedModel)) {
return 0;
}
GroupedModel groupedModel = (GroupedModel)classedModel;
return groupedModel.getGroupId();
}
protected String getUuid(ClassedModel classedModel) throws Exception {
if (classedModel instanceof StagedModel) {
StagedModel stagedModel = (StagedModel)classedModel;
return stagedModel.getUuid();
}
Method getUuidMethod = null;
try {
Class<?> modelClass = classedModel.getClass();
getUuidMethod = modelClass.getMethod("getUuid", new Class<?>[0]);
}
catch (Exception e) {
return StringPool.BLANK;
}
return (String)getUuidMethod.invoke(classedModel, new Object[0]);
}
protected boolean isValid(MethodInvocation methodInvocation, int phase) {
Method method = methodInvocation.getMethod();
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 0) {
if (_log.isDebugEnabled() && (phase == _PHASE_BEFORE)) {
_log.debug(
"The method " + methodInvocation +
" must have at least one parameter");
}
return false;
}
Class<?> parameterType = parameterTypes[0];
if (!ClassedModel.class.isAssignableFrom(parameterType)) {
if (_log.isDebugEnabled() && (phase == _PHASE_BEFORE)) {
_log.debug(
"The first parameter of " + methodInvocation +
" must implement ClassedModel");
}
return false;
}
Object[] arguments = methodInvocation.getArguments();
ClassedModel classedModel = (ClassedModel)arguments[0];
if ((classedModel == null) ||
!(classedModel.getPrimaryKeyObj() instanceof Long)) {
if (_log.isDebugEnabled() && (phase == _PHASE_BEFORE)) {
_log.debug(
"The first parameter of " + methodInvocation +
" must be a long");
}
return false;
}
if (phase != _PHASE_AFTER_RETURNING) {
return true;
}
if (!AuditedModel.class.isAssignableFrom(parameterType) &&
!GroupedModel.class.isAssignableFrom(parameterType) &&
!StagedModel.class.isAssignableFrom(parameterType)) {
if (_log.isDebugEnabled()) {
StringBundler sb = new StringBundler(4);
sb.append("If send is true, the first parameter of ");
sb.append(methodInvocation);
sb.append(" must implement AuditedModel, GroupedModel, or ");
sb.append("StagedModel");
_log.debug(sb.toString());
}
return false;
}
return true;
}
private static final int _PHASE_AFTER_RETURNING = 1;
private static final int _PHASE_BEFORE = 0;
private static final int _PHASE_DURING_FINALLY = 2;
private static final Log _log = LogFactoryUtil.getLog(
SystemEventAdvice.class);
private static final SystemEvent _nullSystemEvent = new SystemEvent() {
@Override
public int action() {
return SystemEventConstants.ACTION_NONE;
}
@Override
public Class<? extends Annotation> annotationType() {
return SystemEvent.class;
}
@Override
public boolean send() {
return false;
}
@Override
public int type() {
return 0;
}
};
}